Apakah ada cara untuk menghasilkan skrip buat dari tabel yang ada murni di T-SQL (yang tanpa menggunakan SMO, karena T-SQL tidak memiliki akses ke SMO). Katakanlah prosedur tersimpan yang menerima nama tabel dan mengembalikan string yang berisi skrip buat untuk tabel yang diberikan?
Sekarang izinkan saya menggambarkan situasi yang saya hadapi, karena mungkin ada cara berbeda untuk mendekati ini. Saya punya contoh dengan beberapa lusin basis data. Semua database ini memiliki skema yang sama, semua tabel yang sama, indeks dan sebagainya. Mereka dibuat sebagai bagian dari instalasi perangkat lunak pihak ketiga. Saya perlu memiliki cara untuk bekerja dengan mereka sehingga saya dapat mengumpulkan data dari mereka secara ad-hoc. Orang-orang baik di dba.se telah membantu saya di sini. Cara membuat pemicu dalam database yang berbeda?
Saat ini saya perlu menemukan cara untuk memilih dari tabel di semua database. Saya telah mencatat semua nama basis data ke dalam tabel yang disebut Databasees
dan saya menulis skrip berikut untuk mengeksekusi pernyataan pilih pada semuanya:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
select * into #tmp from Database1.dbo.Table1 where 1=0
DECLARE @statement nvarchar(max) =
N'insert into #tmp select * from Table1 where Column1=0 and Cloumn2 =1'
DECLARE @LastDatabaseID INT
SET @LastDatabaseID = 0
DECLARE @DatabaseNameToHandle varchar(60)
DECLARE @DatabaseIDToHandle int
SELECT TOP 1 @DatabaseNameToHandle = Name,
@DatabaseIDToHandle = Database_Ref_No
FROM Databasees
WHERE Database_Ref_No > @LastDatabaseID
ORDER BY Database_Ref_No
WHILE @DatabaseIDToHandle IS NOT NULL
BEGIN
DECLARE @sql NVARCHAR(MAX) = QUOTENAME(@DatabaseNameToHandle) + '.dbo.sp_executesql'
EXEC @sql @statement
SET @LastDatabaseID = @DatabaseIDToHandle
SET @DatabaseIDToHandle = NULL
SELECT TOP 1 @DatabaseNameToHandle = Name,
@DatabaseIDToHandle = Database_Ref_No
FROM Databasees
WHERE Database_Ref_No > @LastDatabaseID
ORDER BY Database_Ref_No
END
select * from #tmp
DROP TABLE #tmp
Namun skrip di atas gagal dengan pesan berikut:
Nilai eksplisit untuk kolom identitas dalam tabel '#tmp' hanya dapat ditentukan ketika daftar kolom digunakan dan IDENTITY_INSERT adalah ON.
Menambahkan ini:
SET IDENTITY_INSERT #tmp ON
tidak membantu, karena, saya tidak dapat menentukan daftar kolom dan menyimpannya secara umum.
Dalam SQL tidak ada cara untuk mematikan identitas pada tabel yang diberikan. Anda hanya bisa menjatuhkan kolom dan menambahkan kolom, yang, jelas mengubah urutan kolom. Dan jika urutan kolom berubah, Anda, sekali lagi, perlu menentukan daftar kolom, itu akan berbeda tergantung pada tabel yang Anda query.
Jadi saya berpikir jika saya bisa mendapatkan skrip tabel buat dalam kode T-SQL saya, saya bisa memanipulasinya dengan ekspresi manipulasi string untuk menghapus kolom identitas dan juga menambahkan kolom untuk nama Database ke set hasil.
Adakah yang bisa memikirkan cara yang relatif mudah untuk mencapai apa yang saya inginkan?
sumber
Tidak mungkin untuk T-SQL menghasilkan skrip pembuatan tabel yang lengkap. Setidaknya tidak ada build in way. Anda selalu dapat menulis "generator" Anda sendiri melalui informasi
sys.columns
.Namun dalam kasus Anda, Anda tidak perlu mendapatkan skrip pembuatan lengkap. Yang Anda butuhkan adalah mencegah
SELECT INTO
dari menyalin properti identitas. Cara termudah untuk melakukannya adalah dengan menambahkan perhitungan ke kolom itu. Jadi, bukannyakamu perlu menulis
Untuk menghasilkan pernyataan ini, Anda dapat kembali menggunakan sys.columns seperti pada SQL Fiddle ini
Setup Skema MS SQL Server 2008 :
Dua kolom yang kita butuhkan adalah
name
danis_identity
: Permintaan 1 :Hasil :
Dengan itu kita bisa menggunakan
CASE
pernyataan untuk membuat setiap kolom untuk daftar kolom:Pertanyaan 2 :
Hasil :
Dengan sedikit tipuan XML, kita dapat menggabungkan semua ini bersama-sama untuk mendapatkan daftar kolom lengkap:
Pertanyaan 3 :
Hasil :
Perlu diingat, bahwa Anda tidak dapat membuat tabel #temp menggunakan SQL dinamis dan menggunakannya di luar pernyataan itu karena tabel #temp keluar dari ruang lingkup setelah pernyataan sql dinamis Anda selesai. Jadi Anda harus menekan semua kode Anda ke dalam string SQL dinamis yang sama atau menggunakan tabel nyata. Jika Anda harus dapat menjalankan beberapa skrip / prosedur ini secara bersamaan, Anda perlu memberi kami nama tabel acak, jika tidak mereka akan saling menginjak. Sesuatu seperti
QUOTENAME(N'temp_'+CAST(NEWID() AS NVARCHAR(40))
seharusnya membuat nama yang cukup bagus.Alih-alih menyalin semua data di sekitar, Anda juga bisa menggunakan teknik serupa untuk secara otomatis menghasilkan tampilan untuk setiap tabel yang menyatukan semua inkarnasi dari tabel itu di semua basis data. Namun tergantung pada ukuran tabel yang mungkin lebih cepat atau lebih lambat, jadi Anda harus mengujinya. Jika Anda pergi rute ini, saya akan menempatkan pandangan-pandangan itu ke dalam basis data terpisah.
sumber
Ada skrip yang bagus untuk mencapai hal ini dalam artikel SQLServerCentral:
Versi terbaru skrip saat ini juga tersedia sebagai teks di sini (stormrage.com).
Saya berharap ada cara untuk memasukkan semua skrip di sini, karena itu berfungsi untuk saya. Script terlalu panjang untuk ditempelkan di sini.
Pemberitahuan hak cipta:
sumber
Anda dapat menghasilkan kasar
CREATE TABLE
menggunakan SQL dinamis dari data diINFORMATION_SCHEMA.COLUMNS
.Jika Anda perlu menambahkan batasan dll, Anda perlu menambahkan informasi dari beberapa
INFORMATION_SCHEMA
tampilan lain .Dokumentasi Microsoft
sumber