【问题标题】:How to dynamically choose which table (with same schema) to select from in stored procedure如何在存储过程中动态选择要从哪个表(具有相同架构)中选择
【发布时间】:2010-10-25 16:47:00
【问题描述】:

我的项目有一个奇怪的数据库模型——我将有几个具有相同定义的表。每个表存储不同客户端的信息,并且由于安全限制,我们不能将数据放在一个表中。所以它看起来像这样......


table ClientOneData
(
    Id (PK, int, not null),
    Col1 (varchar(50), not null),
    etc.
)

table ClientTwoData
(
    Id (PK, int, not null),
    Col1 (varchar(50), not null),
    etc.
)

我想要一个存储过程来从相应的表中检索数据。我可以通过将表名作为参数传递给 proc 然后构建一个 sql 字符串来执行...


CREATE PROCEDURE GetData
    @TableName varchar(100)

AS
BEGIN

    DECLARE @sql varchar(max)
    SET @sql = 'SELECT * FROM ' + @sql

    exec(@sql)

...但这对我来说似乎是根本错误的。并且复制代码,无论是以巨大的案例语句的形式,还是通过“一次性”proc 并为每个客户端创建一个新的,似乎也是错误的。

有没有更好的方法来做到这一点?

我非常愿意接受建议,从我可以在 proc 中做的任何事情到重新处理数据模型(没有将所有数据转储到单个表中)。升级到 SQL-Server 2008 或 2010可能是一种选择,但将是最后的手段。

【问题讨论】:

  • 不确定存储过程在此处添加了什么。我会让客户决定选择哪个表。
  • 表中有哪些数据?
  • @Jeremy Wiggins,您能否扩展阻止您将所有客户放在一个表中的安全限制?
  • @Mark Ba​​nnister - 这只是一个要求,正如我们对我们正在构建它的人所说的那样“我们可以将数据放在一个表中并通过一个键将其与不同的公司相关联”他们说“不,数据必须存储在单独的表中”。这就是目前的情况。至少我们能够说服他们不要为每家公司使用单独的数据库。但他们非常重视为公司保留数据。
  • @Jeremy Wiggins,在这种情况下,合并视图看起来是最佳选择 - 但它确实强调了单独表格要求的无意义。

标签: sql sql-server sql-server-2005 stored-procedures


【解决方案1】:

如果您的表数量相当少,您可以将它们组合成一个视图并进行查询。示例:

create view vw_MyTables
AS
   SELECT 'table1' as tableName, * from table1
   UNION
   SELECT 'table2', * from table2 
   UNION
   SELECT 'table3', * from table3 


SELECT * FROM vw_MyTables
WHERE tableName = @TableName

否则我认为你唯一的选择是动态 sql...

如果你愿意改变你的架构,那可能是最好的。您是否有理由在不同的表中为客户存储相同(是否相同?)信息?

我之前使用过以下结构来表示这种类型的数据:

Client
--------
ClientId - pk
ClientName


ClientData
-----------
DataId - pk
ClientId - fk to Client
Whatever

这基本上是我的观点所做的,但如果您这样做,您可以在其上创建索引并快速获取您的数据。

【讨论】:

    【解决方案2】:

    如果您绝对必须将客户的数据分成单独的表,那么我认为动态 SQL 是最好的途径。另一种方法是拥有一个从所有客户端表中进行选择的视图,如下所示:

    create view AllClients as
    select 'ClientOne' ClientName, c1.* from ClientOneData c1 union all
    select 'ClientTwo' ClientName, c2.* from ClientTwoData c2 union all
    .
    .
    .
    etc.
    

    - 但这只是以虚拟形式复制您出于安全原因排除的单个表。

    【讨论】:

      【解决方案3】:

      我会将数据合并到一个表中并实现row-level security,而不是分成单独的表。

      【讨论】:

        【解决方案4】:

        逐字使用参数的动态 SQL 是一个安全漏洞。例如,有人可能会利用您的存储过程并传递一个 drop 命令。

        此外,带有动态 SQL 的存储过程将在每次执行时重新编译。

        使用 Abe Miessler 观点的存储过程是正确的做法:安全且不重新编译。

        【讨论】:

        • 所有这些都可能是,但这不是对所提出问题的答案。
        猜你喜欢
        • 2016-10-05
        • 2014-12-07
        • 2010-12-10
        • 2010-12-02
        • 1970-01-01
        • 1970-01-01
        • 2020-08-06
        • 1970-01-01
        相关资源
        最近更新 更多