2014-09-29 69 views
0

我有一个存储过程,我试图根据提供的tinyint参数有条件地选择一个特定的表。这是我的代码:有条件地选择CASE的表格

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

你不能这样做我害怕。你只能做一组'IF'语句,比如'IF @countryId = 1 SELECT * FROM test_sv ELSE IF @countryId = 2 SELECT * FRMO test_dk etc' – DavidG 2014-09-29 09:42:10

+0

是test_sv,test_dk等表吗?他们有相同的结构吗? – schudel 2014-09-29 09:43:46

+0

是的,结构相同。我希望有条件地选择表的原因是为了避免重现代码,因为我的SELECT语句有些复杂,它会有很多重复的代码。 – Marcus 2014-09-29 10:33:55

回答

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 

Demo

+0

不是最优的,但我想这可能是我的情况下最好的解决方案。谢谢! – Marcus 2014-09-29 10:35:01

+0

请记住,这意味着您的查询计划可能会非常低效。 – DavidG 2014-09-29 10:51:52

+0

这个sproc的结果无论如何都被缓存了,它只被调用一次。 – Marcus 2014-10-07 15:45:19

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. 

但这种方法可能会产生一些奇怪的查询计划和影响性能。一个替代方案是创建一个视图,工会的所有表一起(提供具有相同的结构:

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
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 '[email protected] 

EXEC sp_excecutesql @sql