溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MySQL過程報(bào) Parameter number N is not an OUT parameter錯(cuò)誤

發(fā)布時(shí)間:2020-08-05 08:32:39 來源:ITPUB博客 閱讀:706 作者:壹頁書 欄目:MySQL數(shù)據(jù)庫
坑,絕對(duì)的大坑

今天上線新模塊,昨天測試通過的代碼,居然在線上報(bào)錯(cuò).
報(bào)錯(cuò)信息模擬如下:
MySQL過程報(bào) Parameter number N is not an OUT parameter錯(cuò)誤

納尼?
第一反應(yīng)是程序哪里寫錯(cuò)了
大家查了一上午,問題依舊,毫無頭緒.
后來居然被本貓發(fā)現(xiàn)了問題(頗自豪啊)
這個(gè)其實(shí)是權(quán)限不足導(dǎo)致的.

模擬問題如下:

已經(jīng)存在一個(gè)用戶,對(duì)mvbox庫下的表,有Insert,update,select權(quán)限.
grant select,insert,update on mvbox.* to li@'localhost' identified by 'li';

新建兩個(gè)過程.

  1. drop procedure if exists proc1;
  2. drop procedure if exists proc2;

  3. delimiter $$

  4. create procedure proc1 (in para1 int , out para2 int)
  5. begin
  6.     select para1 into para2;
  7. end $$

  8. create procedure proc2 (in para1 int , out para2 int)
  9. begin
  10.     select para1 into para2;
  11. end $$
  12. delimiter ;
注意, 新建過程之后,沒有對(duì) li 帳號(hào)進(jìn)行授權(quán).

這時(shí)執(zhí)行程序如下


  1. import java.sql.CallableStatement;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Types;

  6. public class T {
  7.     public static void main(String[] args) throws SQLException, ClassNotFoundException {
  8.         Class.forName("com.mysql.jdbc.Driver");
  9.         Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mvbox", "li", "li");

  10.         CallableStatement cp = conn.prepareCall("{call proc1(?,?)}");
  11.         cp.setInt(1, 1);
  12.         cp.registerOutParameter(2, Types.INTEGER);
  13.         cp.execute();
  14.         System.out.println(cp.getInt(2));
  15.         cp.close();
  16.         conn.close();
  17.     }
  18. }

執(zhí)行之后,結(jié)果如下:
MySQL過程報(bào) Parameter number N is not an OUT parameter錯(cuò)誤

增加如下授權(quán)之后,再次執(zhí)行
grant execute on procedure  mvbox.proc1 to  li@'localhost' identified by 'li';

還是報(bào)錯(cuò),報(bào)錯(cuò)信息如下:
Exception in thread "main" java.sql.SQLException: User does not have access to metadata required to determine stored procedure parameter types. If rights can not be granted, configure connection with "noAccessToProcedureBodies=true" to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:997)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:983)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:928)
at com.mysql.jdbc.DatabaseMetaData.getCallStmtParameterTypes(DatabaseMetaData.java:1858)
at com.mysql.jdbc.DatabaseMetaData.getProcedureOrFunctionColumns(DatabaseMetaData.java:4508)
at com.mysql.jdbc.JDBC4DatabaseMetaData.getProcedureColumns(JDBC4DatabaseMetaData.java:106)
at com.mysql.jdbc.CallableStatement.determineParameterTypes(CallableStatement.java:857)
at com.mysql.jdbc.CallableStatement.<init>(CallableStatement.java:630)
at com.mysql.jdbc.JDBC4CallableStatement.<init>(JDBC4CallableStatement.java:46)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.CallableStatement.getInstance(CallableStatement.java:524)
at com.mysql.jdbc.ConnectionImpl.parseCallableStatement(ConnectionImpl.java:4335)
at com.mysql.jdbc.ConnectionImpl.prepareCall(ConnectionImpl.java:4419)
at com.mysql.jdbc.ConnectionImpl.prepareCall(ConnectionImpl.java:4393)
at T.main(T.java:12)

這個(gè)報(bào)錯(cuò)信息就容易理解了,增加對(duì)proc表的select權(quán)限
grant select on mysql.proc to li@'localhost' identified by 'li';

再次執(zhí)行,成功??!

這時(shí)候,如果訪問proc2 過程,則報(bào)錯(cuò)如下:(當(dāng)然會(huì)出錯(cuò),因?yàn)闆]有對(duì)帳號(hào)li進(jìn)行授權(quán)啊)
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: execute command denied to user 'li'@'localhost' for routine 'mvbox.proc2'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1062)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1302)
at com.mysql.jdbc.CallableStatement.execute(CallableStatement.java:921)
at T.main(T.java:15)

但是這個(gè)報(bào)錯(cuò),明確顯示了帳號(hào)li對(duì)于過程mvbox.proc2 沒有執(zhí)行權(quán)限.這樣很容易定位解決問題.

在什么情況下,會(huì)因?yàn)闄?quán)限不足而報(bào)Parameter number N is not an OUT parameter的錯(cuò)誤呢?

就是該帳號(hào)沒有任何execute的授權(quán),而執(zhí)行存儲(chǔ)過程的時(shí)候,就會(huì)有上述報(bào)錯(cuò).

并且僅僅是使用JDBC的途徑,如果使用MySQL 的客戶端,報(bào)錯(cuò)信息也是明確的..

MySQL過程報(bào) Parameter number N is not an OUT parameter錯(cuò)誤


MySQL JDBC的一個(gè)坑,一個(gè)專有大坑.






向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI