2014-01-07 1 views
3

Моя таблицаВставка и обновление массив динамической длины в таблицу

(id int,property varchar) 

Предположим, что я хочу, чтобы вставить {3, 'a, b, c'}. Как это сделать в хранимой процедуре?
Запись таблицы будет:

id property 
3 a 
3 b 
3 c 

Кроме того, когда я хочу, чтобы обновить id=3 строку на {3, 'ab, b, bg, ht'}. Какова будет хранимая процедура для этой операции вставки и обновления? Мои записи таблиц должны стать

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 

EDIT:

для того, чтобы обновить новую использовать колонку в этой таблице:

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 и свойство уникальным.

+0

Это нормально. Однако вполне возможно сделать то, что хочет OP, хотя, по общему признанию, довольно неудобно. – nestedloop

0

Если я хорошо понял, вы могли бы сделать что-то похож к этому:

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

Это просто псевдокод, и вы должны сделать это внутри хранимой процедуры.

Если это правильный подход, вы должны смотреть на это: T-SQL split string

Смежные вопросы