使用java中的表值参数调用存储过程

pra*_*dha 11 sql sql-server parameters stored-procedures jdbc

在我的应用程序中,我想执行查询,如SELECT*FROM tbl WHERE col IN(@list)其中,@ list可以有变量no值.我正在使用MS SQL服务器数据库.当我谷歌这个问题,然后我找到了这个链接

http://www.sommarskog.se/arrays-in-sql-2008.html

此链接表示使用表值参数.所以我使用Microsoft SQL Server Management Studio创建了用户定义的数据类型.

CREATE TYPE integer_list_tbltype AS TABLE(n int NOT NULL PRIMARY KEY)

然后我写了存储过程

CREATE PROCEDURE get_product_names @prodids integer_list_tbltype READONLY AS
   SELECT p.ProductID, p.ProductName
   FROM   Northwind.dbo.Products p
   WHERE  p.ProductID IN (SELECT n FROM @prodids)
Run Code Online (Sandbox Code Playgroud)

然后只使用管理工作室我执行了这个程序

DECLARE @mylist integer_list_tbltype
INSERT @mylist(n) VALUES(9),(12),(27),(37)
EXEC get_product_names @mylist
Run Code Online (Sandbox Code Playgroud)

它给了我正确的输出.但我想知道如何从java源代码调用此存储过程.我知道如何使用常量参数调用简单的存储过程

CallableStatement proc_stmt = null;
proc_stmt = con.prepareCall("{call test(?)}");
proc_stmt.setString(1,someValue);
Run Code Online (Sandbox Code Playgroud)

但如何在表值参数的情况下调用存储过程?

Luk*_*der 6

JDBC驱动程序手册中对此进行了说明。对于您的情况,您必须这样做:

try (SQLServerCallableStatement stmt =
    (SQLServerCallableStatement) con.prepareCall("{call test(?)}")) {

    SQLServerDataTable table = new SQLServerDataTable();   
    sourceDataTable.addColumnMetadata("n", java.sql.Types.INTEGER);   

    sourceDataTable.addRow(9);
    sourceDataTable.addRow(12);
    sourceDataTable.addRow(27);
    sourceDataTable.addRow(37);

    stmt.setStructured(1, "dbo.integer_list_tbltype", table);  
}
Run Code Online (Sandbox Code Playgroud)

我最近也在一篇文章中对此进行了记录


pra*_*dha -7

经过一段时间的搜索,我找到了这个问题的答案。特别是当您使用 IN 子句并且没有操作数是可变的时,您可以使用逗号分隔的值作为 IN 子句中的输入。

下面的示例将使用动态 SQL 来检索所提供的邮政编码中给定律师类型的所有律师的存储过程。

CREATE PROCEDURE [dbo].[GetLawyers] ( @ZIP CHAR(5), @LawyerTypeIDs VARCHAR(100) )
AS

DECLARE @SQL     VARCHAR(2000)

SET @SQL = 'SELECT * FROM [dbo].[Lawyers]
            WHERE [ZIP] = ' + @ZIP + ' AND
                  [LawyerTypeID] IN (' + @LawyerTypeIDs + ')'
EXECUTE (@SQL)

GO
Run Code Online (Sandbox Code Playgroud)

要执行存储过程,传递用户输入的邮政编码和选定的律师,请键入逗号分隔值:

EXECUTE [dbo].[GetLawyers] '12345', '1,4'
Run Code Online (Sandbox Code Playgroud)

所以结论是你不需要使用TVP。无论您使用哪种语言[Java、PHP],只需将参数作为逗号分隔的字符串传递给存储过程,它就会完美运行。

所以在JAVA中你可以调用上面的存储过程:-

proc_stmt = con.prepareCall("{call GetLawyers(?,?)}");
proc_stmt.setString(1,"12345");
proc_stmt.setString(2,"'1,4'");
Run Code Online (Sandbox Code Playgroud)

  • 这样做的问题是它可能会导致 sql 注入 (6认同)
  • 这种方法的问题是它可能会填满语句缓存。 (3认同)
  • 如何将 `@ZIP` 参数设置为 `"0; DROP TABLE [Lawyers]; --"` (3认同)