Matlab 内置的 runstoredprocedure 函数,用来运行同时有输入和输出参数的存储过程:
x = runstoredprocedure(c, 'myproc', {2500, 'Jones'}, {java.sql.Types.NUMERIC})
同事在用的时候发现一个 bug ,但在网上居然找不到相关的信息。该 bug 出现在访问非 SQL 的数据库的储存过程时,至少存在于 R2010b 版。问题出现在对字符串输入参数的处理上( line 50 - 57 ):
%Build stored procedure call spcall = [spcall '(']; for i = 1:length(inarg) if isnumeric(inarg{i}) || islogical(inarg{i}) inarg{i} = num2str(inarg{i},17); elseif strcmp(sDbName,'MySQL') || strcmp(sDbName,'Microsoft SQL Server') inarg{i} = ['''' inarg{i} '''']; end spcall = [spcall inarg{i} ',']; %#ok, not sure how long spcall will be end
上面这段代码是将储存过程的输入参数转化为函数参数的形式
myproc(2500, 'Jones',
但对于 Oracle 数据库或者其它非 SQL 类型的数据库,它被转化为了
myproc(2500, Jones,
上面的 Jones 左右边没有引号,当传入数据库进行执行时,数据库识别不出 Jones 是什么含义,从而导致报错:
??? Java exception occurred:
java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'myproc'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignoredat sun.jdbc.odbc.JdbcOdbc.createSQLException(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.standardError(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(Unknown Source)
修改方法很简单,在 runstoredprocedure 的第 53 行的 elseif 中间加一个%号,即
将
elseif strcmp(sDbName,'MySQL') || strcmp(sDbName,'Microsoft SQL Server')
改成
else%if strcmp(sDbName,'MySQL') || strcmp(sDbName,'Microsoft SQL Server')
也可以下载修改后版本,直接覆盖 Matlab 安装目录下的 \toolbox\database\database\@database\ 目录下的 runstoredprocedure.m。
Q. E. D.