2016-11-22 1 views
1

Как установить параметр @p_ItemShelfList [file].[udtt_ItemShelfPair] READONLY правильно, как сКак установить параметр нулевой табличного типа при вызове хранимой процедуры с JTDS

cs.setNull(3, Types.NULL); 

Когда я пытаюсь что я получаю

Operand type clash: nvarchar is incompatible with udtt_ItemShelfPair

  protected String doInBackground(String... params) { 

     if (DBcard.trim().equals("") || DBshelf.trim().equals("")) 
      z = getString(R.string.Invalid_Credentials); 
     else { 
      try { 
       Connection con = connectionClass.CONN(); 
       if (con == null) { 
        z = getString(R.string.Forbindelses_fejl); 
       } else { 
        String itemcard = DBcard; 
        { 
         if (itemcard.substring(0, 1).startsWith("K")) { 
          itemcard = itemcard.substring(1); 
         } else { 
          itemcard = itemcard;//.substring(0)); 
         } 
        } 
        String itemshelf = DBshelf; 
        { 
         if (itemshelf.substring(0, 1).startsWith("R")) { 
          itemshelf = "" + itemshelf.substring(1); 
         } else { 
          itemshelf = "" + itemshelf;//.substring(0)); 
         } 
        } 
        String doerTicket; 
        doerTicket = setingPreferences.getString("doerTicket", ""); 
        String sql = "{call dbo.usp_assignPartToShelf(?,?,?,?,?)}"; 
        try (CallableStatement s = con.prepareCall(sql)) { 
         s.setString(1, itemshelf); 
         s.setString(2, itemcard); 

         SQLServerDataTable dt = new SQLServerDataTable(); 
         dt.addColumnMetadata("ItemNumber", Types.INTEGER); 
         dt.addColumnMetadata("ShelfNumber", Types.INTEGER); 
         ((SQLServerCallableStatement) s).setStructured(3, "dbo.udtt_ItemShelfPair", dt); 

         s.registerOutParameter(4, Types.INTEGER); 
         s.setString(5, doerTicket); 

         boolean hasResultSet = s.execute(); 
         if (hasResultSet) { 
          try (ResultSet rs = s.getResultSet()) { 
           rs.next(); 
           System.out.printf("ResultSet data: %s%n", rs.getString(1)); 
          } 
         } 
         System.out.printf("Output parameter data: %d%n", s.getInt(4)); 
        } 
       } 
      } catch (Exception ex) { 
       isSuccess = false; 
       z = getString(R.string.Exceptions) + "L2)"; 
       Log.e("MYAPP", "exception", ex); 
      } 
     } 
     return z; 
    } 
} 
ALTER PROCEDURE [file].[usp_assignPartToShelf] 
    @p_ItemNumber VARCHAR (20) = NULL 
    , @p_ShelfNumber NVARCHAR (100) = NULL 
    , @p_ItemShelfList [file].[udtt_ItemShelfPair] READONLY 
    , @p_UpdatedItems INT = 0 OUTPUT 
    , @p_DoerTicket VARCHAR (200) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @doerUserID INT 
      , @doerCompanyID INT 
    EXEC system.usp_validateAuthenticationTicket @p_Ticket = @p_DoerTicket 
               , @p_UserID = @doerUserID OUTPUT 
               , @p_CompanyID = @doerCompanyID OUTPUT 

    DECLARE @res INT 
      , @id INT 

    SET @p_UpdatedItems = 0 

    IF (EXISTS (SELECT TOP 1 1 
       FROM @p_ItemShelfList)) 
    BEGIN 
     DECLARE cur_ISL CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY 
     FOR SELECT i.ID, ISNULL (ti.ShelfNumber, '')AS ShelfNumber 
      FROM @p_ItemShelfList AS ti 
       INNER JOIN [file].Item AS i ON (ti.ItemNumber = i.ItemNumber) 
              AND (i.Type IN ('P', 'N')) 
      WHERE (i.Status < 100) --100: Reserved 

     OPEN cur_ISL 

     FETCH NEXT FROM cur_ISL 
     INTO @id, @p_ShelfNumber 

     WHILE (@@FETCH_STATUS = 0) 
     BEGIN 
      PRINT @id 
      EXEC @res = [file].usp_iudPart @p_ID = @id 
             , @p_ShelfNumber = @p_ShelfNumber 
             , @p_DoerTicket = @p_DoerTicket 
      PRINT @res 
      IF (@res <> 0) 
       BREAK; 

      SET @p_UpdatedItems += 1 

      FETCH NEXT FROM cur_ISL 
      INTO @id, @p_ShelfNumber 
     END 

     CLOSE cur_ISL; 
     DEALLOCATE cur_ISL; 
    END 
    ELSE 
    BEGIN 
     SELECT @id = i.ID 
     FROM [file].Item AS i 
     WHERE i.Company_ID = @doerCompanyID 
      AND i.ItemNumber = @p_ItemNumber 
      AND (i.Type IN ('P', 'N')) 

     IF (@@ROWCOUNT <> 1) 
     BEGIN 
      --RAISERROR ('DBException_InvalidPartNumber', 16, 1) 
      RETURN 10 
     END 

     EXEC @res = [file].usp_iudPart @p_ID = @id 
            , @p_ShelfNumber = @p_ShelfNumber 
            , @p_DoerTicket = @p_DoerTicket 


     SET @p_UpdatedItems += 1 
    END 

    RETURN @res 
END 

сопп класс

import android.annotation.SuppressLint; 
    import android.app.Activity; 
    import android.content.Context; 
    import android.content.SharedPreferences; 
    import android.os.StrictMode; 
    import android.util.Log; 
    import java.sql.SQLException; 
    import java.sql.Connection; 
    import java.sql.DriverManager; 
    import com.microsoft.sqlserver.jdbc.SQLServerDriver; 
    /** 
    * Created by kewin on 07-07-2016. 
    */ 
    public class ConnectionClass { 
     Context context; 
     private SharedPreferences setingPreferences; 
     String ip; 
     String classs = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; 
     String db; 
     String un; 
     String password; 
     public ConnectionClass (Context context) 
     { 
      this.context = context; 
     } 
     @SuppressLint("NewApi") 
     public Connection CONN() { 
      setingPreferences = context.getSharedPreferences("Settings", Activity.MODE_PRIVATE); 
      ip = setingPreferences.getString("server", ""); 
      db = setingPreferences.getString("db", ""); 
      un = setingPreferences.getString("dbuser", ""); 
      password = setingPreferences.getString("dbpass", ""); 
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() 
        .permitAll().build(); 
      StrictMode.setThreadPolicy(policy); 
      Connection conn = null; 
      String ConnURL = null; 
      try { 

       Class.forName(classs); 
       ConnURL = "jdbc:sqlserver://" + ip + ";" 
         + "databaseName=" + db + ";user=" + un + ";password=" 
         + password + ";"; 
       conn = DriverManager.getConnection(ConnURL); 
      } catch (SQLException se) { 
       Log.e("ERRO", se.getMessage()); 
      } catch (ClassNotFoundException e) { 
       Log.e("ERRO", e.getMessage()); 
      } catch (Exception e) { 
       Log.e("ERRO", e.getMessage()); 
      } 
      return conn; 
     } 
    } 

ответ

1

Похоже, что SQL Server не любит получать значение NULL для параметра типа таблицы. Даже вызов хранимой процедуры из SSMS как этого

EXEC [dbo].[usp_assignPartToShelf] @p_ItemShelfList = NULL 

выдает ошибку

Operand type clash: void type is incompatible with udtt_ItemShelfPair

Однако, это принять пустой таблицы, как в следующем примере, который использует «Microsoft драйвер JDBC 6.0 для SQL Сервер»

String sql = "{call dbo.usp_assignPartToShelf(?,?,?,?,?)}"; 
try (CallableStatement s = conn.prepareCall(sql)) { 
    s.setString(1, "testItemNumber"); 
    s.setString(2, "testShelfNumber"); 

    SQLServerDataTable dt = new SQLServerDataTable(); 
    dt.addColumnMetadata("ItemNumber", Types.INTEGER); 
    dt.addColumnMetadata("ShelfNumber", Types.INTEGER); 
    ((SQLServerCallableStatement) s).setStructured(3, "dbo.udtt_ItemShelfPair", dt); 

    s.registerOutParameter(4, Types.INTEGER); 
    s.setString(5, "testDoerTicket"); 

    boolean hasResultSet = s.execute(); 
    if (hasResultSet) { 
     try (ResultSet rs = s.getResultSet()) { 
      rs.next(); 
      System.out.printf("ResultSet data: %s%n", rs.getString(1)); 
     } 
    } 
    System.out.printf("Output parameter data: %d%n", s.getInt(4)); 
} 

Если вам нужно придерживаться jTDS тогда альтернативный подход будет использовать PreparedStatement для запуска би т T-SQL с EXEC утверждением, что просто опускает @p_ItemShelfList из списка аргументов, как это:

String sql = 
     "SET NOCOUNT ON; " + 
     "DECLARE @upd INT; " + 
     "EXEC dbo.usp_assignPartToShelf " + 
       "@p_ItemNumber=?, " + 
       "@p_ShelfNumber=?, " + 
       "@[email protected] OUTPUT, " + 
       "@p_DoerTicket=?;" + 
     "SELECT @upd AS UpdatedItems;"; 
try (PreparedStatement s = conn.prepareStatement(sql)) { 
    s.setString(1, "testItemNumber"); 
    s.setString(2, "testShelfNumber"); 
    s.setString(3, "testDoerTicket"); 
    ResultSet rs = s.executeQuery(); // above T-SQL always returns at least one ResultSet 
    rs.next(); 
    System.out.println(rs.getString(1)); // display something from ResultSet 
    if (s.getMoreResults()) { 
     System.out.printf(
       "INFO:%n" + 
       " A second ResultSet was found.%n" + 
       " The previous ResultSet was returned by the stored procedure.%n" + 
       " Getting next ResultSet ...%n", 
       ""); 
     rs = s.getResultSet(); 
     rs.next(); 
     System.out.println(rs.getString(1)); 
    } 
    rs.close(); 
} 
+0

, когда я выполнить зр из SQL я ничего не к столу только p_ItemNumber p_ShelfNumber p_DoerTicket объявить. и SQLServerDataTable и addColumnMetadata - это то, что мне нужно? так как он не может его решить –

+0

@ KewinBjörkNielsen - Я обновил свой ответ. –

+0

i get a Метод executeQuery должен возвращать набор результатов. на подготовленном заявлении один –

Смежные вопросы