【问题标题】:Transform NULL into target column's default values in a INSERT INTO SELECT query在 INSERT INTO SELECT 查询中将 NULL 转换为目标列的默认值
【发布时间】:2015-03-20 11:28:50
【问题描述】:

是否可以在不必在每个查询中指定(和维护)静态类型的列列表的情况下解决这个问题?

DECLARE @src TABLE (Id INT, Created DATETIME)

INSERT INTO @src
VALUES (1, NULL)

DECLARE @dst TABLE (Id INT, Created DATETIME DEFAULT GETDATE() NOT NULL)

INSERT INTO @dst
   SELECT *
   FROM @src

错误:

无法将值NULL插入列'Created',表'@dst';列不允许空值。

插入失败。

【问题讨论】:

  • 您得到的错误仅仅是因为您已将 dst Created 列声明为“NOT NULL”,并且您试图从 src 插入一个 NULL 值。这有点像红鲱鱼。检查我的答案,以避免在每个查询中输入列列表。

标签: sql-server


【解决方案1】:

那你为什么指定NOT NULL呢?如果仅未指定列,则会触发默认值,这意味着您没有向该列插入任何值。但是,在您的情况下,您正在向表中插入 NULL 值。如果你愿意:

insert into @dst(id) select id from @src

它将插入默认约束。如果插入 NULL,您可以使用触发器将值更改为 GETDATE()。

【讨论】:

  • NULL 不是值。这是VALUE缺失的标志。
  • 这是一个长期讨论的话题。当您将 NULL 插入行时,您希望将行的值设置为 NULL。我知道你在说什么我只是不知道如何解释它。
【解决方案2】:

你可以试试这个代码:

declare @src table (Id int, Created datetime)
insert into @src values(1, null)

declare @dst table (Id int, Created datetime default getdate() not null)
insert into @dst 
select 
    Id,
    COALESCE(Created, GETDATE())
from @src

因此,如果您在第一个表(Created 列)中插入一些日期,然后执行第二个查询,那么第二个表将填充第一个表中的值。如果您甚至想将 NULL 插入到第一个表中,那么在第二个查询中,您必须采取一些解决方法来不允许将显式 NULL 写入第二个表(即COALESCE)。

当然,如果你在第二个查询中省略了Created列,那么会触发DEFAULT约束,它会自己插入GETDATE()值。

【讨论】:

    【解决方案3】:

    使用静态表定义,然后使用“选择 *”来填充它,您必须确保列顺序正确,并且在此期间没有修改表,这可能会影响结果。它充满了危险并且容易出现问题。更好的方法是使用 SELECT INTO 和临时表。如果之前没有创建过表模式,则 SELECT INTO 将创建表模式,从而无需声明。

    SELECT 1 AS [ID], CASE WHEN s.val IS NULL Then GETDATE() ELSE s.Val END as [Created Date]
    INTO #src
    FROM Source s
    
    SELECT s.* 
    INTO #dst d
    from #src s
    

    如果需要,您可以在 select 语句中转换值以使用创建的临时表列类型或 Put Case 语句逻辑。

    【讨论】:

      【解决方案4】:

      我不确切知道您在尝试什么,但这可行,并且由于它的表变量我认为以这种方式使用它没有问题,因此我假设了更多价值

      DECLARE @src TABLE (Id INT, Created DATETIME)
      INSERT INTO @src VALUES (1, NULL)
      INSERT INTO @src VALUES (1, '2015-01-01')
      
      DECLARE @dst TABLE (Id INT, Created DATETIME NOT NULL)
      INSERT INTO @dst
      SELECT s.Id,
             CASE WHEN s.Created IS NULL THEN GETDATE() ELSE s.Created END
      FROM   @src s
      

      SQLFidlle:http://sqlfiddle.com/#!6/9eecb/1367

      【讨论】:

      • 问题是他从第一个表@src 中选择了NULL,然后尝试显式地将NULL 插入到第二个表的Created 列中
      • @veljasije 你能看到更新吗,我想我明白你的评论了吗?
      猜你喜欢
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-08
      相关资源
      最近更新 更多