我正在尝试调试别人的SQL报告,并将基础报告查询放入SQL 2012的查询窗口。
报告要求的参数之一是整数列表。这是通过多选下拉框在报告上实现的。报告的基础查询在where
子句中使用此整数列表,例如
select *
from TabA
where TabA.ID in (@listOfIDs)
我不想修改我正在调试的查询,但我无法弄清楚如何在SQL Server上创建一个可以保存此类数据的变量来测试它。
e.g。
declare @listOfIDs int
set listOfIDs = 1,2,3,4
没有可以保存整数列表的数据类型,那么如何在我的SQL Server上使用与报表相同的值运行报表查询?
答案 0 :(得分:179)
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
答案 1 :(得分:25)
假设变量类似于:
Screen 1 (iPad): <UIScreen: 0x1567def0; bounds = {{0, 0}, {480, 320}}; mode = <UIScreenMode: 0x1567dd60; size = 1024.000000 x 768.000000>>
Screen 2 (MacBook): <UIScreen: 0x15680280; bounds = {{0, 0}, {640, 400}}; mode = <UIScreenMode: 0x156804a0; size = 1280.000000 x 800.000000>>:
存储过程以这种形式使用它:
CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [int] NOT NULL
)
您可以创建IntList并像这样调用过程:
ALTER Procedure [dbo].[GetFooByIds]
@Ids [IntList] ReadOnly
As
或者如果您自己提供IntList
Declare @IDs IntList;
Insert Into @IDs Select Id From dbo.{TableThatHasIds}
Where Id In (111, 222, 333, 444)
Exec [dbo].[GetFooByIds] @IDs
答案 2 :(得分:14)
你是对的,SQL-Server中没有可以保存整数列表的数据类型。但你可以做的是将整数列表存储为字符串。
DECLARE @listOfIDs varchar(8000);
SET @listOfIDs = '1,2,3,4';
然后,您可以将字符串拆分为单独的整数值,并将它们放入表中。您的程序可能已经这样做了。
您还可以使用动态查询来实现相同的结果:
DECLARE @SQL nvarchar(8000);
SET @SQL = 'SELECT * FROM TabA WHERE TabA.ID IN (' + @listOfIDs + ')';
EXECUTE (@SQL);
答案 3 :(得分:4)
对于SQL Server 2016+和Azure SQL数据库,添加了STRING_SPLIT函数,这将是解决此问题的完美解决方案。这是文档: here
以下是一个例子:
/*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
〜干杯
答案 4 :(得分:3)
最后我得出的结论是,如果不修改查询的工作原理,我就无法将值存储在变量中。我使用SQL分析器来捕获值,然后将它们硬编码到查询中以查看它是如何工作的。这些整数数组中有18个,其中一些包含超过30个元素。
我认为MS / SQL需要在语言中引入一些附加的数据类型。数组很常见,我不明白为什么你不能在存储过程中使用它们。
答案 5 :(得分:2)
您不能这样做,但您可以执行将其存储在变量中的整个查询。
例如:
DECLARE @listOfIDs NVARCHAR(MAX) =
'1,2,3'
DECLARE @query NVARCHAR(MAX) =
'Select *
From TabA
Where TabA.ID in (' + @listOfIDs + ')'
Exec (@query)
答案 6 :(得分:1)
如果使用字符串列表,则SQL中有一个名为string_split
的新函数。
引用链接STRING_SPLIT (Transact-SQL)
DECLARE @tags NVARCHAR(400) = 'clothing,road,,touring,bike'
SELECT value
FROM STRING_SPLIT(@tags, ',')
WHERE RTRIM(value) <> '';
您可以通过in
传递此查询,如下所示:
SELECT *
FROM [dbo].[yourTable]
WHERE (strval IN (SELECT value FROM STRING_SPLIT(@tags, ',') WHERE RTRIM(value) <> ''))
答案 7 :(得分:0)
我用这个:
1-在建筑物脚本中声明一个临时表变量:
DECLARE @ShiftPeriodList TABLE(id INT NOT NULL);
2-分配给临时表:
IF (SOME CONDITION)
BEGIN
INSERT INTO @ShiftPeriodList SELECT ShiftId FROM [hr].[tbl_WorkShift]
END
IF (SOME CONDITION2)
BEGIN
INSERT INTO @ShiftPeriodList
SELECT ws.ShiftId
FROM [hr].[tbl_WorkShift] ws
WHERE ws.WorkShift = 'Weekend(VSD)' OR ws.WorkShift = 'Weekend(SDL)'
END
3-在WHERE语句中需要时引用表:
INSERT INTO SomeTable WHERE ShiftPeriod IN (SELECT * FROM @ShiftPeriodList)