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
〜干杯