我有一个存储过程,我试图根据提供的tinyint
参数有条件地选择特定的表。这是我的代码:
ALTER PROCEDURE [dbo].[GetAllStuff]
@countryId tinyint
AS
BEGIN
SET NOCOUNT ON;
DECLARE @marketSpecific TABLE
SET @marketSpecific =
(CASE (@countryId)
WHEN 1 THEN test_sv
WHEN 2 THEN test_dk
WHEN 3 THEN test_no
WHEN 4 THEN test_ge
ELSE test_sv
END)
[..]
END
不幸的是,这不起作用。我收到以下错误:
'必须声明标量变量@marketSpecific
列名称test_sv无效
显然我误解了CASE的工作原理。任何人都可以提供任何见解吗?
答案 0 :(得分:1)
您无法在CASE语句中选择要使用的表。你可以这样做:
IF @countryId = 1
SELECT * FROM test_sv
ELSE IF @countryId = 2
SELECT * FROM test_dk
ELSE IF @countryId = 3
SELECT * FROM test_no
... etc.
但是这种方法可能会产生一些奇怪的查询计划并影响性能。另一种方法是创建一个UNION将所有表放在一起的视图(提供具有相同结构的视图:
CREATE VIEW test_all
AS
SELECT 1 AS table_type, col1, col2, col3 FROM test_sv
UNION
SELECT 2 AS table_type, col1, col2, col3 FROM test_sdk
UNION
SELECT 3 AS table_type, col1, col2, col3 FROM test_no
UNION
... etc.
现在,您可以在存储过程中查询该视图,如下所示:
ALTER PROCEDURE [dbo].[GetAllStuff]
@countryId tinyint
AS
BEGIN
SELECT * FROM test_all WHERE table_type = @countryId
答案 1 :(得分:1)
您可以将动态查询编写为:
create PROCEDURE [dbo].[GetAllStuff]
@countryId tinyint
AS
BEGIN
SET NOCOUNT ON
DECLARE @IntVariable int
DECLARE @SQLString nvarchar(500)
DECLARE @marketSpecific varchar(100)
/* Assign parameter value to local variable to avoid parameter sniffing */
SET @IntVariable = @countryId
SET @marketSpecific = (CASE (@IntVariable)
WHEN 1 THEN 'test_sv'
WHEN 2 THEN 'test_dk'
WHEN 3 THEN 'test_no'
WHEN 4 THEN 'test_ge'
ELSE 'test_sv'
END)
/* Build the SQL string one time.*/
SET @SQLString =
N'SELECT *
FROM '+ @marketSpecific
EXECUTE sp_executesql @SQLString
END
答案 2 :(得分:1)
DECLARE @countryId TINYINT =1,
@sql NVARCHAR(max),
@marketSpecific VARCHAR(10)
SELECT @marketSpecific = CASE @countryId
WHEN 1 THEN 'test_sv'
WHEN 2 THEN 'test_dk'
WHEN 3 THEN 'test_no'
WHEN 4 THEN 'test_ge'
ELSE 'test_sv' END
Set @sql='select * from '+@marketSpecific
EXEC sp_excecutesql @sql