【问题标题】:Create a foreign key constraint in a stored procedure with input primary key table name使用输入主键表名在存储过程中创建外键约束
【发布时间】:2016-01-26 14:42:31
【问题描述】:

我正在编写一个存储过程,它创建一个名称作为输入提供的表。我通过使用临时名称 _TMP 创建表来完成此操作:

--Create the table with a temp name since the variable name
--cannot be used in the "CREATE TABLE" statement.
CREATE TABLE [dbo].[_TMP]
(
    [EntryID] [uniqueidentifier] NOT NULL,
    CONSTRAINT [PK__TMP] PRIMARY KEY CLUSTERED 
    (
        [EntryID] ASC
    )
    WITH 
    (
        PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
        IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
        ALLOW_PAGE_LOCKS  = ON
    )
)

然后像这样重命名它:

EXEC SP_RENAME N'_TMP', @TargetTableName

现在我想添加另一个输入,即 现有 主键表的名称,以便我可以在新表中设置外键关系。假设我还在名为ParentEntryID 的新表中创建了 FK 列。

ALTER TABLE [dbo].[_TMP]  WITH CHECK 
ADD  CONSTRAINT [FK__TMP__TMP_PARENT] FOREIGN KEY([ParentEntryID])
REFERENCES [dbo].[_TMP_PARENT] ([EntryID]) -- <-- this won't work b/c there's no such table _TMP_PARENT

ALTER TABLE [dbo].[_TMP] CHECK CONSTRAINT [FK__TMP__TMP_PARENT]

正如上面评论中所指出的,问题在于该过程将失败,因为我无法使用REFERENCES 子句提供实际的主键表名称。 是否有系统 sp 可以处理用于设置外键关系的变量表名?我还没有找到。

【问题讨论】:

  • 不是您实际问题的答案(抱歉),但您可以创建表然后使用 EXEC(string) 命令创建 FK 吗?另外-您要么想将新表的名称用于约束,要么也重命名它们……否则您将只能执行一次;-)
  • @bri -- 谢谢,是的,为了简洁起见,我省略了约束的重命名。我希望在没有动态 sql 的情况下做到这一点。
  • 您想要的只是一个边缘案例,而动态 SQL 几乎是实现此目的的唯一方法。使用sp_executeSQL 通常比EXECUTE 更安全。

标签: sql-server sql-server-2008 stored-procedures sql-server-2008-r2


【解决方案1】:

首先,如果您需要创建具有新名称和相同结构的表,则存在设计问题。这不是一个好的技术,是一种数据库反模式。

但是,如果你坚持使用它,你需要使用动态 sql 创建表和索引。请在在线图书中查找如何做到这一点,并首先阅读这篇文章:

http://www.sommarskog.se/dynamic_sql.html

【讨论】:

  • 感谢您的回答。我有兴趣更多地了解为什么这不是一种好的技术和反模式。如果我解释一下我在做什么,也许会有所帮助:这些表是为存储在其他地方发生的某些数据的更改而创建的日志表。它们的创建结构与起点相同,因为所有此类表都应具有一组已知的元字段。稍后由另一个进程添加特定的日志数据列。一些日志表共享父/子关系——因此是我的问题。如果您能指导我采用另一种方法,我会很高兴。
  • ...或者更多关于这个反模式的阅读(它具体叫什么,所以我可以查一下?)
猜你喜欢
  • 2017-03-24
  • 1970-01-01
  • 2023-04-02
  • 2018-05-01
  • 1970-01-01
  • 2023-04-05
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多