Czy istnieje sposób na wygenerowanie skryptu tworzenia z istniejącej tabeli wyłącznie w języku T-SQL (bez użycia SMO, ponieważ T-SQL nie ma dostępu do SMO). Powiedzmy, że procedura składowana, która otrzymuje nazwę tabeli i zwraca ciąg znaków, który zawiera skrypt tworzenia dla danej tabeli?
Teraz opiszę sytuację, w której się znajduję, ponieważ może istnieć inny sposób podejścia do tego. Mam instancję z kilkadziesiąt baz danych. Te bazy danych mają ten sam schemat, wszystkie tabele, indeks i tak dalej. Zostały one utworzone w ramach instalacji oprogramowania innej firmy. Muszę mieć sposób na współpracę z nimi, aby móc agregować dane z nich w sposób ad hoc. Mili ludzie z dba.se już mi pomogli. Jak utworzyć wyzwalacz w innej bazie danych?
Obecnie muszę znaleźć sposób na dokonanie wyboru z tabeli we wszystkich bazach danych. Zapisałem wszystkie nazwy baz danych w tabeli o nazwie Databasees
i napisałem następujący skrypt do wykonania instrukcji select na wszystkich z nich:
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
Jednak powyższy skrypt kończy się niepowodzeniem i pojawia się następujący komunikat:
Wyraźną wartość kolumny tożsamości w tabeli „#tmp” można określić tylko wtedy, gdy używana jest lista kolumn, a IDENTITY_INSERT jest włączony.
Dodanie tego:
SET IDENTITY_INSERT #tmp ON
nie pomaga, ponieważ nie mogę określić listy kolumn i zachować jej ogólnego charakteru.
W SQL nie ma możliwości wyłączenia tożsamości w danej tabeli. Możesz tylko upuścić kolumnę i dodać kolumnę, co oczywiście zmienia kolejność kolumn. A jeśli zmieni się kolejność kolumn, musisz ponownie określić listę kolumn, która będzie różna w zależności od tabeli, której dotyczy zapytanie.
Pomyślałem więc, czy mogę uzyskać skrypt tworzenia tabeli w moim kodzie T-SQL, mógłbym nim manipulować za pomocą wyrażeń manipulacji ciągiem, aby usunąć kolumnę tożsamości, a także dodać kolumnę z nazwą bazy danych do zestawu wyników.
Czy ktoś może wymyślić stosunkowo łatwy sposób na osiągnięcie tego, czego chcę?
źródło
Nie jest możliwe, aby T-SQL wygenerował pełny skrypt tworzenia tabeli. Przynajmniej nie ma żadnej kompilacji. zawsze możesz napisać własny „generator” przeglądający informacje
sys.columns
.Ale w twoim przypadku nie potrzebujesz pełnego skryptu tworzenia. Wszystko, czego potrzebujesz, to zapobiec
SELECT INTO
kopiowaniu właściwości tożsamości. Najłatwiej to zrobić, dodając obliczenia do tej kolumny. Więc zamiastmusisz pisać
Aby wygenerować tę instrukcję, możesz ponownie użyć sys.columns jak w tym SQL Fiddle
Konfiguracja schematu MS SQL Server 2008 :
Dwie kolumny Potrzebujemy
name
ais_identity
: Zapytanie 1 :Wyniki :
Dzięki temu możemy użyć
CASE
instrukcji do wygenerowania każdej kolumny dla listy kolumn:Zapytanie 2 :
Wyniki :
Przy odrobinie sztuczki XML możemy połączyć to wszystko razem, aby uzyskać pełną listę kolumn:
Zapytanie 3 :
Wyniki :
Należy pamiętać, że nie można utworzyć tabeli #temp przy użyciu dynamicznego SQL i używać jej poza tą instrukcją, ponieważ tabela #temp wychodzi poza zakres po zakończeniu dynamicznej instrukcji SQL. Musisz więc wycisnąć cały kod w ten sam dynamiczny ciąg SQL lub użyć prawdziwej tabeli. Jeśli musisz być w stanie wykonać wiele z tych skryptów / procedur w tym samym czasie, musisz nam losową nazwę tabeli, w przeciwnym razie będą się nawzajem nadepnąć. Coś takiego
QUOTENAME(N'temp_'+CAST(NEWID() AS NVARCHAR(40))
powinno mieć wystarczająco dobre imię.Zamiast kopiować wszystkie dane, możesz również użyć podobnej techniki, aby po prostu automatycznie wygenerować widok dla każdej tabeli, która łączy wszystkie wcielenia tej tabeli we wszystkich bazach danych. W zależności od wielkości stołu może to być jednak szybsze lub wolniejsze, dlatego należy go przetestować. Jeśli pójdziesz tą drogą, umieściłbym te widoki w osobnej bazie danych.
źródło
W tym artykule SQLServerCentral jest dobry skrypt do osiągnięcia tego:
Aktualna najnowsza wersja skryptu jest również dostępna jako tekst tutaj (stormrage.com).
Chciałbym, żeby był tu sposób na dołączenie całego skryptu, ponieważ działa dla mnie. Skrypt jest po prostu za długi, aby go wkleić.
Informacja o prawach autorskich:
źródło
Możesz wygenerować zgrubny
CREATE TABLE
za pomocą dynamicznego SQL z danych wINFORMATION_SCHEMA.COLUMNS
.Jeśli chcesz dodać ograniczenia itp., Musisz dodać informacje z niektórych innych
INFORMATION_SCHEMA
widoków.Dokumentacja Microsoft
źródło