将列添加到现有的SQL Server表 - 含义

6

我在SQL Server中有一个现有的表,其中有现有条目(实际上超过100万条)。

这个表被前端应用程序定期更新、插入和选择。我想/需要添加一个datetime列,例如M_DateModified,可以像下面这样更新:

UPDATE Table SET M_DateModified = GETDATE()

每当前端按下按钮并调用存储过程时,将会按照要求将该列添加到现有报告中。
我的问题及答案是:作为我们应用程序的核心表之一,更改表并添加其他列是否会破坏现有查询?显然,您不能在未指定所有列的值的情况下插入到表中,因此任何现有的插入查询都将失效(这是一个巨大的问题)。
关于这个问题,任何帮助都将不胜感激。

4
它会破坏糟糕设计的查询 - 例如 SELECT * FROM .... 或者没有明确指定要插入的列列表的 INSERT 查询..... - marc_s
4
你说“显然,如果不为所有列指定值,就无法向表中插入数据”。这并不正确。 - RBarryYoung
1
抱歉,@RBarryYoung。我的意思是,如果只使用简单的插入语句,你会收到“列名或提供的值的数量与表定义不匹配”的消息。例如,如果你只提供了5个值,而表需要7个值呢?请原谅我的新手错误,我还不太熟悉这个。 :) - frans
啊,是的,就是默认的 INSERT。我已经忘记了它,但是因为它相当于在 INSERT 中使用 "*",所以不应该那样做(现在你知道为什么了)。请明确指定您的列。 - RBarryYoung
谢谢,以后会注意的 :) - frans
4个回答

7
首先,正如marc_s所说,它只会影响SELECT *查询,甚至其中并不一定会全部受到影响。
其次,在INSERT中,您只需要指定所有非空字段,因此如果将其设为可空,您就不必担心这个问题。此外,对于类似Created_Date的列,通常会设置一个DEFAULT值为=GetDate(),如果未指定,则会自动为其填充。
第三,如果您仍然担心会影响现有的代码库,请执行以下操作:
1. 将表重命名为类似"physicalTable"的名称。 2. 创建一个具有与您的表以前相同名称的视图,该视图使用SELECT .. FROM physicalTable,以相同顺序显式列出列,但不要在其中包含M_DateModified字段。 3. 将您的代码保持不变,现在引用该视图,而不是直接访问表。
现在您的代码可以安全地与表交互,而不需要更改(SQL DML代码无法区分表和可写视图)。
最后,这种"ModifiedDate"列是常见需求,并且通常首先使其可为空,然后添加一个Insert & Update触发器来自动设置它:
UPDATE t
SET    M_DateModified = GetDate()
FROM   (SELECT * FROM physicalTable y JOIN inserted i ON y.PkId = i.PkId) As t

通过这种方式,应用程序无需自己维护该字段。作为额外的奖励,应用程序也不能将其设置错误或虚假(这是SQL触发器的常见且可接受的用途)。


1
如果新列不是必需的,您就不用担心了。除非您有一些笨蛋使用 "*" 而不是列列表编写 select 语句。

这样的查询可能确实存在。该应用程序非常庞大。 - frans
2
或者其他那些写INSERT INTO dbo.Table VALUES(.....)而不指定要使用的列列表的傻瓜们 - 如果添加新的列(无论是否是必需的),这些插入语句都会全部失效... - marc_s

1
只要你的SELECT不使用通配符*,那么它们就应该没有问题。对于INSERT语句,如果将字段设置为默认值GETDATE()并允许为空,则可以排除该字段而仍然填充它。

1
取决于您的其他查询设置。如果它们是SELECT [Item1],[Item2],等等... 那么您不会遇到任何问题。如果是SELECT * FROM,则可能会出现一些意外的结果。
请记住您想如何设置它,您要么必须将其设置为可空,这可能会导致未来出现问题,要么设置默认日期,这可能会导致报告、检索、查询等方面出现错误的数据。

这绝对也是需要考虑的事情。考虑到这将用于报告。谢谢。 - frans

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