SQLvariables来保存整数列表

我试图debugging别人的SQL报告,并将基础报告查询放入SQL 2012的查询窗口中。

报告要求的参数之一是整数列表。 这是通过多选下拉框在报告上实现的。 报表的底层查询在where子句中使用了这个整数列表

 select * from TabA where TabA.ID in (@listOfIDs) 

我不想修改我正在debugging的查询,但我不知道如何在SQL Server上创build一个可以容纳这种types的数据来testing它的variables。

例如

 declare @listOfIDs int set listOfIDs = 1,2,3,4 

没有可以保存整数列表的数据types,那么如何在报表中使用与报表相同的值在SQL Server上运行报表查询?

表variables

 declare @listOfIDs table (id int); insert @listOfIDs(id) values(1),(2),(3); select * from TabA where TabA.ID in (select id from @listOfIDs) 

要么

 declare @listOfIDs varchar(1000); SET @listOfIDs = ',1,2,3,'; --in this solution need put coma on begin and end select * from TabA where charindex(',' + CAST(TabA.ID as nvarchar(20)) + ',', @listOfIDs) > 0 

假设这个variables是类似的东西:

 CREATE TYPE [dbo].[IntList] AS TABLE( [Value] [int] NOT NULL ) 

存储过程以这种forms使用它:

 ALTER Procedure [dbo].[GetFooByIds] @Ids [IntList] ReadOnly As 

您可以创buildIntList并像这样调用过程:

 Declare @IDs IntList; Insert Into @IDs Select Id From dbo.{TableThatHasIds} Where Id In (111, 222, 333, 444) Exec [dbo].[GetFooByIds] @IDs 

你是对的,在SQL-Server中没有可以容纳一个整数列表的数据types。 但是你可以做的是将一个整数列表存储为一个string。

 DECLARE @listOfIDs varchar(8000); SET @listOfIDs = '1,2,3,4'; 

然后,您可以将string拆分为单独的整数值并将其放入一个表中。 你的程序可能已经这样做了。

您也可以使用dynamic查询来实现相同的结果:

 DECLARE @SQL nvarchar(8000); SET @SQL = 'SELECT * FROM TabA WHERE TabA.ID IN (' + @listOfIDs + ')'; EXECUTE (@SQL); 

最后我得出的结论是,如果不修改查询的工作方式,我不能将值存储在variables中。 我使用SQL分析器来捕获值,然后将其硬编码到查询中,以查看它是如何工作的。 有18个这样的整型数组,有些有30多个元素。

我认为MS / SQL需要在语言中引入一些辅助数据types。 数组是相当普遍的,我不明白为什么你不能在存储过程中使用它们。

你不能这样做,但你可以执行整个查询存储在一个variables。

例如:

 DECLARE @listOfIDs NVARCHAR(MAX) = '1,2,3' DECLARE @query NVARCHAR(MAX) = 'Select * From TabA Where TabA.ID in (' + @listOfIDs + ')' Exec (@query) 

对于SQL Server 2016+和Azure SQL数据库,添加了STRING_SPLIT函数,这将是解决此问题的完美scheme。 这里是文档: https : //docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

这里是一个例子:

 /*List of ids in a comma delimited string Note: the ') WAITFOR DELAY ''00:00:02''' is a way to verify that your script doesn't allow for SQL injection*/ DECLARE @listOfIds VARCHAR(MAX) = '1,3,a,10.1,) WAITFOR DELAY ''00:00:02'''; --Make sure the temp table was dropped before trying to create it IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable; --Create example reference table CREATE TABLE #MyTable ([Id] INT NOT NULL); --Populate the reference table DECLARE @i INT = 1; WHILE(@i <= 10) BEGIN INSERT INTO #MyTable SELECT @i; SET @i = @i + 1; END /*Find all the values Note: I silently ignore the values that are not integers*/ SELECT t.[Id] FROM #MyTable as t INNER JOIN (SELECT value as [Id] FROM STRING_SPLIT(@listOfIds, ',') WHERE ISNUMERIC(value) = 1 /*Make sure it is numeric*/ AND ROUND(value,0) = value /*Make sure it is an integer*/) as ids ON t.[Id] = ids.[Id]; --Clean-up DROP TABLE #MyTable; 

查询的结果是1,3

〜干杯