2014-01-07 41 views
3

我的表是插入和更新動態長度的數組到表

(id int,property varchar) 

假設我想插入{3, 'a, b, c'}。我如何在存儲過程中執行此操作?
的表項是:

id property 
3 a 
3 b 
3 c 

此外,當我想{3, 'ab, b, bg, ht'}更新我id=3行。這個插入和更新操作的存儲過程是什麼?我的表項應成爲

id property 
3 ab 
3 b 
3 bg 
3 ht 
+0

的版本是不正確的。它改變了最初的想法。應該是{3,'a,b,c'} – Ventura

+0

這意味着我的id是3,屬性是{a,b,c}。每個屬性項目有三個表格條目。 – zooney

+0

我試着通過先刪除匹配的行然後插入新行來解決上述問題。我正在尋找解決問題的有效方法。並通過使用'合併't-clausen.dk回答是非常適合我的問題。一定要重新打開我的問題,因爲它啓發了SQL合併的方法。 – zooney

回答

3

示例表:

create table yourtable (id int,property varchar(5)) 

程序該表:

create procedure p_test 
(
@id int, 
@prolist varchar(2000) 
) as 
begin 
;with x as 
(
    SELECT * FROM yourtable WHERE id = @ID 
) 
MERGE INTO 
x t1 
using 
(SELECT @id id, ltrim(t.c.value('.', 'VARCHAR(2000)')) property 
FROM (
    SELECT x = CAST('<t>' + 
     REPLACE(@prolist, ',', '</t><t>') + '</t>' AS XML) 
) a 
CROSS APPLY x.nodes('/t') t(c)) t2 on t1.id = t2.id and t1.property = t2.property 
when not matched then INSERT (id,property) 
VALUES(t2.id, t2.property) 
when matched 
THEN UPDATE SET t1.id = t2.id 
WHEN NOT MATCHED BY SOURCE THEN DELETE 
; 
end 

測試:

exec p_test 3, 'b,c' 
select * from yourtable 
exec p_test 3, 'a,b,c' 
select * from yourtable 
exec p_test 3, 'a,c' 
select * from yourtable 
exec p_test 4, 'g,h' 
select * from yourtable 

結果:

id property 
3 b 
3 c 

id property 
3 b 
3 c 
3 a 

id property 
3 c 
3 a 

id property 
4 g 
3 c 
3 a 
4 h 

編輯:

爲了更新一個新的列使用此表:

create table yourtable (id int,property varchar(5), is_active bit default 1) 

使用此過程:

alter procedure p_test 
(
@id int, 
@prolist varchar(2000) 
) as 
begin 
;with x as 
(
    SELECT * FROM yourtable WHERE id = @ID 
) 
MERGE INTO 
x t1 
using 
(SELECT @id id, ltrim(t.c.value('.', 'VARCHAR(2000)')) property 
FROM (
    SELECT x = CAST('<t>' + 
     REPLACE(@prolist, ',', '</t><t>') + '</t>' AS XML) 
) a 
CROSS APPLY x.nodes('/t') t(c)) t2 on t1.id = t2.id and t1.property = t2.property 
when not matched then INSERT (id,property, is_active) 
VALUES(t2.id, t2.property, 1) 
when matched 
THEN UPDATE SET t1.id = t2.id, is_active = 1 
WHEN NOT MATCHED BY SOURCE THEN 
UPDATE SET t1.is_active = 0 
; 
end 
+0

非常感謝。一個小的查詢,你可以給出合併背後的想法。另外,如果'my_table'有一列is_active,而不是在源不匹配時刪除該行,我想將is_active更新爲0.如何操作? – zooney

+0

:對上述查詢有幫助嗎? – zooney

+0

@zooney這是一個很好的問題。我現在不知道。可能需要在存儲過程中創建另一個表達式 –

1

第一招:

insert into <tableName>(id, property) values(3, 'a'); 
insert into <tableName>(id, property) values(3, 'b'); 
insert into <tableName>(id, property) values(3, 'c'); 

第二期:

update <tableName> set property='ab' where property = 'a'; 
update <tableName> set property='bg' where property = 'c'; 
insert into <tableName>(id, property) values(3, 'ht'); 

而現在,一個問題:你確定這是你的問題需要什麼?通常,當我們調用列id時,我們希望它是標識符,即每行都是唯一的。這可能有點偏離主題,但以防萬一......

+0

:遠高於場景只是一個例子。數據將是動態的。 – zooney

+0

@zooney我明白。然後嘗試這些查詢,他們應該工作。用你的表名代替並給它一個去。 – nestedloop

0

應該有一個id /主鍵將是唯一的。根據獨特的領域獲取任何獨特的領域並更新記錄。或者,您可以使財產獨一無二,或者使用一對id和財產。

+0

這是正常情況。然而,完全可能做到OP想要的,雖然公然相當尷尬。 – nestedloop

0

如果我深知,你可以做一些類似此:

Insert INTO @tempTable 
    SELECT 3, * FROM dbo.splitstring('a,b,c,d') 

這只是一個,你應該做你的存儲過程中。

如果這是你必須看看這個正確的方法:T-SQL split string