Sebelum menjawab, izinkan saya mengatakan terlebih dahulu bahwa menurut saya bukan yang terbaik untuk mencatat semua tabel ke dalam satu tabel. Jika database Anda tumbuh, Anda bisa berakhir dengan pertengkaran serius di tabel Log. Plus, semua data Anda harus diubah menjadi varchar atau sql_variant agar dapat ditempatkan di kolom yang sama, sehingga membutuhkan lebih banyak ruang. Saya juga berpikir bahwa mencatat setiap kolom yang diperbarui ke baris terpisah (melewati kolom yang tidak diperbarui) akan membuatnya sangat sulit bagi Anda untuk bertanya. Apakah Anda tahu cara menggabungkan semua data itu untuk benar-benar mendapatkan tampilan gabungan dan masuk akal dari setiap perubahan baris, kapan, dan oleh siapa? Memiliki satu tabel log per tabel, menurut saya, akan jauh lebih mudah. Maka Anda tidak akan mengalami masalah yang Anda alami saat mencoba membuatnya bekerja.
Juga, tahukah Anda tentang SQL Server 2008 Ubah Pengambilan Data ? Gunakan itu sebagai gantinya, jika Anda menggunakan SQL Server edisi Enterprise atau Developer!
Selain masalah itu, Anda dapat melakukan apa yang Anda inginkan dengan UNPIVOT logis (melakukan versi Anda sendiri). Anda tidak dapat benar-benar menggunakan Native SQL 2005 UNPIVOT karena Anda memiliki dua kolom target, bukan satu. Berikut adalah contoh untuk SQL Server 2005 dan lebih tinggi menggunakan CROSS APPLY untuk melakukan UNPIVOT:
INSERT INTO dbo.LOG (Id_Table, Table_Key_Value, Id_Value, Old_Value, New_Value)
SELECT 12345, I.Id, X.Id_Value, X.Old_Value, X.New_Value
FROM
INSERTED I
INNER JOIN DELETED D ON I.ID = D.ID
CROSS APPLY (
SELECT 4556645, D.Name, I.Name
UNION ALL SELECT 544589, D.Surname, I.Surname
) X (Id_Value, Old_Value, New_Value)
WHERE
X.Old_Value <> X.New_Value
Berikut adalah metode yang lebih umum untuk SQL 2000 atau DBMS lainnya (secara teoritis harus bekerja di Oracle, MySQL, dll. -- untuk Oracle tambahkan FROM DUAL
untuk setiap SELECT dalam tabel turunan):
INSERT INTO dbo.LOG (Id_Table, Table_Key_Value, Id_Value, Old_Value, New_Value)
SELECT *
FROM (
SELECT
12345,
I.Id,
X.Id_Value,
CASE X.Id_Value
WHEN 4556645 THEN D.Name
WHEN 544589 THEN D.Surname
END Old_Value,
CASE X.Id_Value
WHEN 4556645 THEN I.Name
WHEN 544589 THEN I.Surname
END New_Value
FROM
INSERTED I
INNER JOIN DELETED D ON I.ID = D.ID
CROSS JOIN (
SELECT 4556645
UNION ALL SELECT 544589
) X (Id_Value)
) Y
WHERE
Y.Old_Value <> Y.New_Value
SQL Server 2005 dan yang lebih baru memang memiliki perintah UNPIVOT asli, meskipun secara umum, bahkan ketika UNPIVOT akan bekerja, saya lebih suka menggunakan CROSS APPLY karena ada lebih banyak fleksibilitas untuk melakukan apa yang saya inginkan. Secara khusus, perintah UNPIVOT asli tidak dapat diterapkan di sini karena UNPIVOT hanya dapat menargetkan satu kolom tujuan, tetapi Anda memerlukan dua (Nilai_Lama, Nilai_Baru). Menggabungkan dua kolom menjadi satu nilai (dan memisahkan nanti) tidak baik; membuat nilai korelator baris yang tidak berarti ke PIVOT dengan sesudahnya tidak baik, dan saya tidak dapat memikirkan cara lain untuk melakukannya yang bukan merupakan variasi dari keduanya. Solusi CROSS APPLY benar-benar akan menjadi yang terbaik bagi Anda untuk mencocokkan struktur tabel log persis seperti yang telah Anda jelaskan.
Dibandingkan dengan kueri saya di sini, metode #1 Anda tidak akan berkinerja baik (dalam rasio sekitar {jumlah kolom}:1 kinerja yang lebih buruk). Metode #2 Anda adalah ide yang bagus tetapi masih kurang optimal karena memanggil UDF memiliki overhead yang besar, ditambah lagi Anda harus mengulang setiap baris (bergidik).