从数据库字段获取表名

4

我使用SQL Server Management Studio 17.0。我有一个表,用于控制不同文件的单独表,类似于:

 filename | tablename
 ---------+----------
 file1    | table1
 file2    | table2

我需要从表中进行选择select from tablename,但不是硬编码的。文件名来自 Web,我可以首先获取表名,例如:

select tablename 
from filetables 
where filename = "file1"

并使用它来查看文件表:

select * 
from (table1)

有没有办法在SQL中完成这个操作?类似于:
Select * 
from 
    (select tablename 
     from filetables 
     where filename = "file1")

4
你只能通过动态SQL(例如存储过程)来实现此操作。尽管不总是如此,但这通常表明数据库设计较差。表中还有其他表,或表中存在字段的表(或者一个数据库中包含了另一个数据库)是数据库设计中常见的反模式。所以这条路可能会带来很多痛苦。 - JNevill
不幸的是,这就是前团队留下的。现在我们需要修复大量的问题,这对我们来说非常痛苦 - 我感觉重新从头开始写应用程序可能会更容易。 - Salek
2个回答

3

如果你需要从一个只能在运行时和/或根据某个参数确定的表中进行选择,那么你唯一的选择是在这种情况下使用动态SQL,但要确保不会暴露自己受到SQL注入攻击的风险。

这里提供了如何安全地创建动态SQL的链接。


-1
   DECLARE @v_sql        NVARCHAR(MAX),
           @v_table_name NVARCHAR(MAX),
           @v_file_name  NVARCHAR(MAX)

    SELECT @v_file_name  = 'file1' -- Populated from web proc

    SELECT @v_table_name = tablename
      FROM filetables
     WHERE filename = REPLACE(@v_file_name, '''', '') 

    SELECT @v_sql =

   'SELECT *
      FROM ' + @v_table_name + '
     WHERE filename = ''' + @v_file_name + ''''

    SELECT @v_sql -- Debug code to show you the statement prior to running

    EXEC sp_executesql @v_sql

你需要像其他用户一样使用动态SQL。在你的环境中尝试一下,看看效果如何。


尽管您正在使用sp_executesql,但这仍然容易受到SQL注入攻击的威胁。 - Icarus
是的,你说得对。我假设提问者会阅读你提供的链接,而我只是为他们的需求提供了一个基本的可执行文件。你说得对,这需要进行清理。 - James Luxton
我已经编辑了代码,以清理Web过程提供的文件名。 - James Luxton
这样也行不通。你需要对语句本身进行参数化,而不是进行字符串拼接和替换。我的链接中有一个正确的示例。 - Icarus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接