使用原始默认属性值将一个表的一部分插入另一个表

Posted

技术标签:

【中文标题】使用原始默认属性值将一个表的一部分插入另一个表【英文标题】:Insert part of one table into another with original default attribute value 【发布时间】:2017-12-14 21:33:35 【问题描述】:

我有两个具有以下架构的表,

table1 (a int, b int, c int, d int 默认123) table2 (a int, b int, c int, e int)

我想将table2(a,b,c) 列更新为table1,但保留d 的默认值。

比如下面的记录

------------------------
table1 | a | b | c | d |
------------------------
       | 1 | 2 | 3 | 4 |
------------------------

------------------------
table2 | a | b | c | e |
------------------------
       | 5 | 6 | 7 | 8 |
------------------------

我想要一个输出:

--------------------------
table1 | a | b | c | d   |
--------------------------
       | 1 | 2 | 3 | 4   |
       | 5 | 6 | 7 | 123 |
--------------------------

这是我尝试过的:

INSERT INTO table1(a, b, c, d) 
VALUES ((SELECT a, b, c FROM table2), DEFAULT)

此查询的语法无效,因为它返回子查询中的表并将其用作值。

我也试图避免下面的这种解决方案,因为它隐藏了使用默认值d 的事实。我真的很想明确地将其设为默认以使其清楚。

INSERT INTO table1(a, b, c) 
    SELECT a, b, c  
    FROM table2

有没有办法结合

INSERT .. VALUES(..)

INSERT.. SELECT.. FROM table

或者只是实现相同目标的另一种方式?

【问题讨论】:

INSERT INTO table1(a, b, c) SELECT a, b, c FROM table2 有什么问题? 看看this问题。 【参考方案1】:

以下代码查找特定表中特定列的默认值定义,并将其拼凑成一个整数。然后可以使用该值在其他语句中显式提供默认值,例如insert.

-- if object_id( N'Samples', N'U' ) is not NULL
--   drop table Samples;

create table Samples ( Id Int Identity, Foo Int Default 42, Bar Int );

-- Get the default value from the metadata.
declare @FooDefaultValue as NVarChar(32); -- Note:   sys.default_constraints.definition   is declared as   NVarChar(max) .
select @FooDefaultValue = sdf.definition
  from sys.tables as st inner join
    sys.columns as sc on sc.object_id = st.object_id inner join
    sys.default_constraints as sdf on sdf.object_id = sc.default_object_id
    where st.name = 'Samples' and sc.name = 'Foo';
select @FooDefaultValue as 'Default Value NVarChar';

-- Cobble it from a string to an integer (since we know the correct data type).
declare @FooDefaultValueInteger as Int =
  Cast( Replace( Replace( @FooDefaultValue, '(', '' ), ')', '' ) as Int );
select @FooDefaultValueInteger as 'Default Value Integer';

-- Insert a few rows with data for both columns.
insert into Samples ( Foo, Bar )
  select Foo, Bar
    from ( values ( 1, 1 ), ( 2, 2 ), ( 3, 3 ) ) as Arthur( Foo, Bar );

-- Insert a few rows with an explicit default value for   Foo .
insert into Samples ( Foo, Bar )
  select @FooDefaultValueInteger, Bar
    from ( values ( 5 ), ( 6 ), ( 7 ) ) as Dent( Bar );

-- Display the results.
select * from Samples;

drop table Samples;

这充其量是笨拙的。从字符串到整数的拼凑让我觉得很脆弱。它可能应该对模式名称进行更多验证,...。当桌子是临时的时,它会变得更有趣。如果表是变量,则完全解开。通过将获取默认值与其使用分开,它打开了名称不一致的可能性,即在不编辑表或列名称的情况下快速剪切粘贴可能会导致坏事

总而言之,我会避免这种情况,并在insert 附近或中添加评论,解释应该发生的事情。

【讨论】:

谢谢。如果这是最简单的方法,那么我认为您已经完全回答了我的问题。正如您提到的,我还将坚持使用评论解决方案,因为我的意图是简化(不隐藏相关信息)。我对 sql 很陌生,仍在尝试学习 do-s 和 don't-s 的语法。这就是为什么这个问题对你来说听起来有点奇怪。 您总是可以转到Microsoft Connect 并建议一个新的SQL Server 函数ColumnDefault( <column name> ) 返回一个与列的数据类型匹配的sql_variant 会很有用。屏住呼吸是不可取的。【参考方案2】:
INSERT INTO table1 values (a, b, c) 
    SELECT a, b, c FROM table2

【讨论】:

谢谢。这当然是正确的。但我正在寻找一个解决方案,其中default 关键字用于属性d 不鼓励使用纯代码答案。

以上是关于使用原始默认属性值将一个表的一部分插入另一个表的主要内容,如果未能解决你的问题,请参考以下文章

如何在更新/插入之前创建一个异常,我必须将一个表的属性值与另一个表的属性值进行比较?

雪花我们如何遍历临时表的每一行并将其值插入到另一个表中,其中每个字段的值都是单行?

用另一个 MySQL 表的值更新一个 MySQL 表(原始表的数据类型是 JSOn)

如何将一个表中的值插入另一个表,然后更新原始表?

插入引用另一个表的值

使用 JDBC 将引用另一个表的数据插入 MySQL