sql-server - select语句中的变量表名

标签 sql-server tsql stored-procedures

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

我正在编写一个存储过程来检索特定 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 语句重写此过程,还是应该使用表名作为变量?

最佳答案

您不能使用 case .. when 在 FROM 子句中的表之间进行切换(就像在 conditional ORDER 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 一样,请注意,替换到查询中的未参数化值(例如@table)会使查询容易受到 Sql 注入(inject)攻击。因此,我建议您确保 @table 来自可信来源,或者更好的是,将 @table 的值与允许的白名单进行比较执行查询之前的表。

关于sql-server - select语句中的变量表名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19807236/

相关文章:

sql - 获取第一个分隔符之前的第一个单词

sql - 使用 JOIN 时的 WHERE 子句与 ON

sql-server - 在更新语句中引发错误

mysql - 将 null 值传递给 Mysql 中的存储过程

Java/PostgreSQL - 性能数据优化

sql - 将 datediff 显示为秒、毫秒

sql-server - SQL Server : drop all databases except the system ones

java - java 调用中的过程调用不起作用

sql - 为什么在SQL Server中像 `select last`一样没有 `select bottom`或 `select top`?

sql-server - 如何通过 TSQL 从 SQL Server 查询中生成 JSON 字符串?