4

我有一些表用于存储不同的文件信息,例如拇指、图像、数据表,...

我正在编写一个存储过程来检索特定 ID 的文件名。就像是:

    CREATE PROCEDURE get_file_name(
    @id int,
    @table nvarchar(50)
    )as
    if @table='images'
        select [filename] from images
        where id = @id
    if @table='icons'
        select [filename] from icons
        where id = @id
....

如何使用case when语句重写此过程,还是应该只使用表名作为变量?

4

3 回答 3

5

您不能使用 case .. when 在 FROM 子句中的表之间切换(就像您可以在conditionalORDER BY中一样)。即如下:

select * from 
    case when 1=1
      then t1
      else t2
    end;

不会工作。

因此,您需要使用动态 SQL。最好尽可能将查询参数化,例如@id可以将值参数化:

-- Validate @table is E ['images', 'icons', ... other valid names here]
DECLARE @sql NVARCHAR(MAX)
SET @sql = 'select [filename] from **TABLE** where id = @id';
SET @sql = REPLACE(@sql, '**TABLE**', @table);

sp_executesql @sql, N'@id INT', @id = @id;

与所有动态 Sql 一样,请注意unparameterized替换到查询中的值(如@table)会使查询容易受到 Sql 注入攻击。因此,我建议您确保@table来自受信任的来源,或者更好的是,@table在执行查询之前将 的值与允许的表的白名单进行比较。

于 2013-11-06T08:46:50.507 回答
3

只需在另一个变量中构建 SQL 字符串并执行它

DECLARE @sql AS NCHAR(500)
SET @sql=
    'SELECT [filename] '+
    ' FROM '+@table+
    ' WHERE id = @id'
EXECUTE(@sql)
于 2013-11-06T08:37:39.620 回答
1
CREATE PROCEDURE get_file_name(
    @id int,
    @table nvarchar(50)
    )as

DECLARE @SQL nvarchar(max);
SET @SQL = 'select [filename] from ' + @table + ' where id = ' + @id
EXECUTE (@SQL)
于 2013-11-06T08:39:10.477 回答