在一对多关系中使用 table 2 中的值更新 Table 1 备注字段
Update Table 1 memo field with values from table 2 in a one-to-many relationship
我有 2 个 table 我想用 table 2 中的值更新 table 1 中的一列,其中 id=id。但是 table 2 有很多行匹配 table 1 并且 table 2 的所有行都需要更新为 table 1
中的 1 行
Table_A
id | all_names |
---+-----------------+
1 |AB CD FG HI |
2 | |
** Table_B **
id | name |
---+-------+
1 | |
2 | Jon |
2 | Mike |
更新后 Table 1 应该看起来像
id | all_names |
---+-----------------+
1 |AB CD FG HI |
2 |Jon Mike |
我试过了
update a
set a.all_names = TRIM(a.all_names) + b.name + ' '
from table_a a, table_b b
where a.id = b.id
我最终得到的只是 table_a
中的空 all_names
有什么想法吗?
除了循环之外,我真的看不到任何其他方法。
DECLARE @id int
DECLARE @name varchar(50)
SELECT * INTO #temp FROM TABLE_B
WHILE EXISTS (SELECT 1 FROM #temp)
BEGIN
SELECT @id = (SELECT TOP 1 id from #temp)
SELECT @name = (SELECT TOP 1 [name] from #temp where id = @id)
UPDATE A
SET all_names = LTRIM(RTRIM(all_names + CHAR(32) + @name))
FROM Table_A A
WHERE A.id = @id
DELETE FROM #temp WHERE id = @id and [name] = @name
END
DROP TABLE #temp
查询将table B 的内容放入临时的table,并在使用后删除该行。因此,基本上所有名称在其自己的 ID 循环中都保持相同的值,除了 space + 每次添加下一个名称。我还在更新中添加了 trim 以防止前导/尾随 space。
我不知道这是否有帮助,但这是严格使用 SQL 的 Oracle 版本。你没有在你的要求中提到它,但是第二次合并防止了行中的重复条目:
创建表并插入示例行
DROP TABLE table_a;
DROP TABLE table_b;
CREATE TABLE table_a
(
id INTEGER
, all_names VARCHAR2 (128)
);
CREATE TABLE table_b
(
id INTEGER
, name VARCHAR2 (10)
);
INSERT INTO table_a (id, all_names)
VALUES (1, 'AB CD FG HI');
INSERT INTO table_a (id, all_names)
VALUES (2, NULL);
INSERT INTO table_b (id, name)
VALUES (1, NULL);
INSERT INTO table_b (id, name)
VALUES (2, 'Jon');
INSERT INTO table_b (id, name)
VALUES (2, 'Mike');
COMMIT;
允许重复合并
MERGE INTO table_a ta
USING (SELECT DISTINCT id, LISTAGG (name, ' ') WITHIN GROUP (ORDER BY name) OVER (PARTITION BY id) names
FROM table_b) tb
ON (ta.id = tb.id)
WHEN MATCHED
THEN
UPDATE SET all_names = all_names || tb.names
WHEN NOT MATCHED
THEN
INSERT (
ta.id, ta.all_names
)
VALUES (
tb.id, tb.names
);
SELECT *
FROM table_a;
ROLLBACK;
合并消除重复项
MERGE INTO table_a ta
USING (SELECT DISTINCT id, LISTAGG (name, ' ') WITHIN GROUP (ORDER BY name) OVER (PARTITION BY id) names
FROM (WITH
aset
AS
(SELECT id, TRIM (all_names) || ' ' AS all_names
FROM table_a),
bset (id, name, REMAINDER)
AS
(SELECT id
, SUBSTR (all_names, 1, INSTR (all_names, ' ') - 1) name
, SUBSTR (all_names, INSTR (all_names, ' ') + 1) REMAINDER
FROM aset
UNION ALL
SELECT id
, SUBSTR (REMAINDER, 1, INSTR (REMAINDER, ' ') - 1) name
, SUBSTR (REMAINDER, INSTR (REMAINDER, ' ') + 1) REMAINDER
FROM bset
WHERE name IS NOT NULL)
SELECT id, name
FROM bset
WHERE name IS NOT NULL
UNION
SELECT id, name
FROM table_b
WHERE name IS NOT NULL)) tb
ON (ta.id = tb.id)
WHEN MATCHED
THEN
UPDATE SET all_names = tb.names
WHEN NOT MATCHED
THEN
INSERT (ta.id, ta.all_names)
VALUES (tb.id, tb.names);
SELECT *
FROM table_a;
--ROLLBACK;
我最后做了什么
Declare @Crs cursor as select * from Table_B; //Temp Table
open @crs;
while fetch @crs do
update Table_A set all_names=ifnull(Table_B,'')+trim(@crs.name)+' ' where
id=@Crs.id;
end while;
close @crs;
这使用最少的行并且很优雅
我有 2 个 table 我想用 table 2 中的值更新 table 1 中的一列,其中 id=id。但是 table 2 有很多行匹配 table 1 并且 table 2 的所有行都需要更新为 table 1
中的 1 行Table_A
id | all_names |
---+-----------------+
1 |AB CD FG HI |
2 | |
** Table_B **
id | name |
---+-------+
1 | |
2 | Jon |
2 | Mike |
更新后 Table 1 应该看起来像
id | all_names |
---+-----------------+
1 |AB CD FG HI |
2 |Jon Mike |
我试过了
update a
set a.all_names = TRIM(a.all_names) + b.name + ' '
from table_a a, table_b b
where a.id = b.id
我最终得到的只是 table_a
中的空 all_names有什么想法吗?
除了循环之外,我真的看不到任何其他方法。
DECLARE @id int
DECLARE @name varchar(50)
SELECT * INTO #temp FROM TABLE_B
WHILE EXISTS (SELECT 1 FROM #temp)
BEGIN
SELECT @id = (SELECT TOP 1 id from #temp)
SELECT @name = (SELECT TOP 1 [name] from #temp where id = @id)
UPDATE A
SET all_names = LTRIM(RTRIM(all_names + CHAR(32) + @name))
FROM Table_A A
WHERE A.id = @id
DELETE FROM #temp WHERE id = @id and [name] = @name
END
DROP TABLE #temp
查询将table B 的内容放入临时的table,并在使用后删除该行。因此,基本上所有名称在其自己的 ID 循环中都保持相同的值,除了 space + 每次添加下一个名称。我还在更新中添加了 trim 以防止前导/尾随 space。
我不知道这是否有帮助,但这是严格使用 SQL 的 Oracle 版本。你没有在你的要求中提到它,但是第二次合并防止了行中的重复条目:
创建表并插入示例行
DROP TABLE table_a;
DROP TABLE table_b;
CREATE TABLE table_a
(
id INTEGER
, all_names VARCHAR2 (128)
);
CREATE TABLE table_b
(
id INTEGER
, name VARCHAR2 (10)
);
INSERT INTO table_a (id, all_names)
VALUES (1, 'AB CD FG HI');
INSERT INTO table_a (id, all_names)
VALUES (2, NULL);
INSERT INTO table_b (id, name)
VALUES (1, NULL);
INSERT INTO table_b (id, name)
VALUES (2, 'Jon');
INSERT INTO table_b (id, name)
VALUES (2, 'Mike');
COMMIT;
允许重复合并
MERGE INTO table_a ta
USING (SELECT DISTINCT id, LISTAGG (name, ' ') WITHIN GROUP (ORDER BY name) OVER (PARTITION BY id) names
FROM table_b) tb
ON (ta.id = tb.id)
WHEN MATCHED
THEN
UPDATE SET all_names = all_names || tb.names
WHEN NOT MATCHED
THEN
INSERT (
ta.id, ta.all_names
)
VALUES (
tb.id, tb.names
);
SELECT *
FROM table_a;
ROLLBACK;
合并消除重复项
MERGE INTO table_a ta
USING (SELECT DISTINCT id, LISTAGG (name, ' ') WITHIN GROUP (ORDER BY name) OVER (PARTITION BY id) names
FROM (WITH
aset
AS
(SELECT id, TRIM (all_names) || ' ' AS all_names
FROM table_a),
bset (id, name, REMAINDER)
AS
(SELECT id
, SUBSTR (all_names, 1, INSTR (all_names, ' ') - 1) name
, SUBSTR (all_names, INSTR (all_names, ' ') + 1) REMAINDER
FROM aset
UNION ALL
SELECT id
, SUBSTR (REMAINDER, 1, INSTR (REMAINDER, ' ') - 1) name
, SUBSTR (REMAINDER, INSTR (REMAINDER, ' ') + 1) REMAINDER
FROM bset
WHERE name IS NOT NULL)
SELECT id, name
FROM bset
WHERE name IS NOT NULL
UNION
SELECT id, name
FROM table_b
WHERE name IS NOT NULL)) tb
ON (ta.id = tb.id)
WHEN MATCHED
THEN
UPDATE SET all_names = tb.names
WHEN NOT MATCHED
THEN
INSERT (ta.id, ta.all_names)
VALUES (tb.id, tb.names);
SELECT *
FROM table_a;
--ROLLBACK;
我最后做了什么
Declare @Crs cursor as select * from Table_B; //Temp Table
open @crs;
while fetch @crs do
update Table_A set all_names=ifnull(Table_B,'')+trim(@crs.name)+' ' where
id=@Crs.id;
end while;
close @crs;
这使用最少的行并且很优雅