Параметры Sybase IN и OUT - PullRequest
       68

Параметры Sybase IN и OUT

5 голосов
/ 30 апреля 2011

Я схожу с ума от того, как драйвер Sybase JDBC обрабатывает хранимые процедуры со смешанными параметрами IN и OUT.Посмотрите на эту простую хранимую процедуру:

CREATE OR REPLACE PROCEDURE p (IN i1 INT, OUT o1 INT, IN i2 INT, OUT o2 INT)
BEGIN
    set o1 = i1;
    set o2 = i2;
END

А вот как я бы назвал ее с JDBC:

CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));

Но это приводит к

1
null

Чтопродолжается??Это действительно злая ошибка в драйвере JDBC или я что-то упустил?Методом проб и ошибок я нашел способ, которым это работает:

c.setInt(1, 1);
c.setInt(2, 2);
c.registerOutParameter(3, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));

Теперь результат равен

1
2

Неужели драйвер JDBC тайно переупорядочивает IN иOUT параметры ??

Я использую SQL Anywhere 12 и jconn3.jar

Ответы [ 3 ]

7 голосов
/ 10 мая 2011

Похоже на ошибку в драйвере.

Я подозреваю, что неисправный драйвер ожидает, что параметры будут переданы / зарегистрированы в порядке (т. Е. 1,2,3,4). Когда вы выполняете registerOut (2), оператор, очевидно, забывает, что вы установили (3): -)

Или, может быть, все OUT должны быть выполнены после всех IN. Опять же, это ошибка в драйвере.

UPDATE

Подождите, вы не изменили процедуру для второго варианта? Этот результат не имеет смысла . Если, как вы сказали, водитель не меняет порядок. Что необычно , если не сказать больше.

ОБНОВЛЕНИЕ 2

Я декомпилировал драйвер. Он делает довольно забавные игры вокруг параметров, и, несмотря на всю эту шумиху, я чувствую, что у них есть серьезный потенциал для ошибки, но до сих пор я не вижу этого явно.

Единственное, что я заметил, это то, что, если параметр в позиции n отсутствует, драйвер будет сканировать параметры вперед, пока не найдет значение; если значение не найдено, оно переходит к следующей строке:

  s.registerOutParameter(5,Types.INT);
  ...
  // no out value at position 4, it will go to 5 and get the value
  rs.getInteger(4);

ОБНОВЛЕНИЕ 3

Может быть интересно увидеть выходные данные всех 4 параметров в примере 1, т.е.:

CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(1));
System.out.println(c.getObject(2));
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
4 голосов
/ 09 мая 2011

Я пробовал это с Oracle 9.2, и он работает как положено .. Я думаю, что эта проблема связана с вашим драйвером JDBC, а не с самим JDBC.

    public static void main(String[] args) throws Exception {

    Connection connection = getConnection();

    CallableStatement c = connection.prepareCall("{ call p(?, ?, ?, ?) }");
    c.setInt(1, 1);
    c.setInt(3, 2);
    c.registerOutParameter(2, Types.INTEGER);
    c.registerOutParameter(4, Types.INTEGER);
    c.execute();
    System.out.println(c.getObject(2));
    System.out.println(c.getObject(4));

}

Выход:

Connected to database
1
2
1 голос
/ 13 января 2014
Below sybase stored procedure works for me
public String IDGEN(String tableName,  Connection con , LOG _log)
    { 
        String strReturnValue = "-1"; 
        try
        {
             CallableStatement cs = con.prepareCall("{call usp_NEWPK_string_v6(?,?)}");
             cs.registerOutParameter(2,java.sql.Types.NUMERIC);
             cs.setString(1,tableName);
             cs.setInt(2,0);
             cs.execute();
             strReturnValue = cs.getLong(2) + "";

        } catch (Exception ex) {
            _log.logInstance(" ERROR: [IDGEN] " + ex.getMessage()); 
        }
        return strReturnValue;
    } 
// abobjects.com

create proc usp_NEWPK_string_v6 (@tablename  varchar(32) , @ID  numeric output
          )
as
declare @newValue     numeric
declare @oldValue  numeric
select @oldValue=IDGEN_ID from DB_IDGEN where IDGEN_TableName = @tablename
select @newValue=@oldValue + 1 from DB
 _IDGEN where IDGEN_TableName = @tablename
update DB_IDGEN set IDGEN_ID = @newValue where IDGEN_TableName = @tablename
select @ID  = @oldValue
return
...