有条件地选择CASE表

时间:2014-09-29 09:38:41

标签: sql sql-server tsql stored-procedures

我有一个存储过程,我试图根据提供的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的工作原理。任何人都可以提供任何见解吗?

3 个答案:

答案 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

Demo

答案 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