1) Dalam jangka menengah atau panjang saya ingin menormalkan database ini untuk menghindari kesalahan seperti:menyimpan daftar nilai dalam kolom string/VARCHAR. Sebagai contoh, saya akan menggunakan tabel berikut banyak ke banyak:
CREATE TABLE dbo.BillItem (
ID INT IDENTITY(1,1) PRIMARY KEY,
BilldID INT NOT NOT NULL REFERENCES dbo.Bill(BilldID),
ItemID INT NOT NULL REFERENCES dbo.Item(ItemID),
UNIQUE (BillID, ItemID) -- Unique constraint created in order to prevent duplicated rows
);
Dalam hal ini, satu tagihan dengan dua item berarti saya harus memasukkan dua baris ke dalam dbo.BillItem
tabel.
2) Kembali ke permintaan awal:untuk satu kali tugas saya akan menggunakan XML dan XQuery dengan demikian (solusi ini diakhiri dengan pernyataan SELECT tetapi sepele untuk diubah menjadi UPDATE):
DECLARE @iCountRef VARCHAR(100) = '1,2,3'
DECLARE @SourceTable TABLE (
BillId INT,
LineReference VARCHAR(8000)
)
INSERT @SourceTable (BillId, LineReference)
VALUES
(100, '1,2,'),
(100, '1,2,40,34'),
(100, '1'),
(100, '12')
DECLARE @iCountRefAsXML XML = CONVERT(XML, '<a><b>' + REPLACE(@iCountRef, ',', '</b><b>') + '</b></a>')
SELECT *, STUFF(z.LineReferenceAsXML.query('
for $i in (x/y)
for $j in (a/b)
where data(($i/text())[1]) eq data(($j/text())[1])
return concat(",", ($i/text())[1])
').value('.', 'VARCHAR(8000)'), 1, 1, '') AS NewLineReference
FROM (
SELECT *, CONVERT(XML,
'<x><y>' + REPLACE(LineReference, ',', '</y><y>') + '</y></x>' +
'<a><b>' + REPLACE(@iCountRef, ',', '</b><b>') + '</b></a>'
) AS LineReferenceAsXML
FROM @SourceTable s
) z
Hasil:
BillId LineReference NewLineReference LineReferenceAsXML
----------- ------------- ---------------- ------------------------------------------------------------------------
100 1,2, 1 ,2 <x><y>1</y><y>2</y><y /></x><a><b>1</b><b>2</b><b>3</b></a>
100 1,2,40,34 1 ,2 <x><y>1</y><y>2</y><y>40</y><y>34</y></x><a><b>1</b><b>2</b><b>3</b></a>
100 1 1 <x><y>1</y></x><a><b>1</b><b>2</b><b>3</b></a>
100 12 (null) <x><y>12</y></x><a><b>1</b><b>2</b><b>3</b></a>