Есть ли способ сгенерировать сценарий создания из существующей таблицы исключительно в T-SQL (то есть без использования SMO, поскольку T-SQL не имеет доступа к SMO). Допустим, хранимая процедура, которая получает имя таблицы и возвращает строку, содержащую сценарий создания для данной таблицы?
Теперь позвольте мне описать ситуацию, с которой я сталкиваюсь, поскольку может быть другой подход к этому. У меня есть экземпляр с несколькими десятками баз данных. Все эти базы данных имеют одинаковую схему, все одинаковые таблицы, индексы и так далее. Они были созданы как часть сторонней установки программного обеспечения. Мне нужно иметь способ работать с ними, чтобы я мог собирать данные из них в произвольном порядке. Хорошие люди на dba.se уже помогли мне здесь Как создать триггер в другой базе данных?
В настоящее время мне нужно найти способ сделать выбор из таблицы во всех базах данных. Я записал все имена баз данных в таблицу с именем Databasees
и написал следующий скрипт для выполнения оператора select для всех из них:
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
Однако вышеприведенный скрипт завершается неудачно со следующим сообщением:
Явное значение для столбца идентификаторов в таблице '#tmp' можно указывать только в том случае, если используется список столбцов, а IDENTITY_INSERT установлен в ON.
Добавление этого:
SET IDENTITY_INSERT #tmp ON
не помогает, так как я не могу указать список столбцов и сделать его общим.
В SQL нет способа отключить идентификацию для данной таблицы. Вы можете только удалить столбец и добавить столбец, который, очевидно, меняет порядок столбцов. И если порядок столбцов изменяется, вам снова нужно указать список столбцов, который будет отличаться в зависимости от таблицы, которую вы запрашиваете.
Поэтому я подумал, что если бы я мог получить скрипт создания таблицы в своем коде T-SQL, я мог бы манипулировать им с помощью выражений манипуляции со строками, чтобы удалить столбец идентификаторов, а также добавить столбец для имени базы данных. в набор результатов.
Кто-нибудь может придумать относительно простой способ добиться того, чего я хочу?
источник
В T-SQL невозможно создать полный сценарий создания таблицы. По крайней мере, нет пути в пути. Вы всегда можете написать свой собственный «генератор», просматривая информацию
sys.columns
.Но в вашем случае вам не нужно получать полный сценарий создания. Все, что вам нужно, это предотвратить
SELECT INTO
копирование свойства идентификации. Самый простой способ сделать это - добавить вычисление в этот столбец. Так что вместотебе нужно написать
Чтобы сгенерировать этот оператор, вы можете снова использовать sys.columns, как в этой скрипте SQL
Настройка схемы MS SQL Server 2008 :
Две колонны , нам нужны
name
иis_identity
: Запрос 1 :Результаты :
С этим мы можем использовать
CASE
оператор для генерации каждого столбца для списка столбцов:Запрос 2 :
Результаты :
С небольшой хитростью XML мы можем объединить все это вместе, чтобы получить полный список столбцов:
Запрос 3 :
Результаты :
Имейте в виду, что вы не можете создать таблицу #temp с использованием динамического SQL и использовать ее вне этого оператора, поскольку таблица #temp выходит из области действия после завершения выполнения вашего динамического оператора sql. Поэтому вам нужно либо сжать весь ваш код в одну и ту же динамическую строку SQL, либо использовать реальную таблицу. Если вам необходимо выполнять несколько этих сценариев / процедур одновременно, вам нужно использовать случайное имя таблицы, иначе они будут наступать друг на друга. Что-то вроде
QUOTENAME(N'temp_'+CAST(NEWID() AS NVARCHAR(40))
должно сделать достаточно хорошее имя.Вместо того, чтобы копировать все данные вокруг, вы также можете использовать аналогичную технику, чтобы просто автоматически генерировать представление для каждой таблицы, объединяющее все воплощения этой таблицы во всех базах данных. Однако, в зависимости от размера таблицы, это может быть быстрее или медленнее, поэтому вы должны проверить это. Если вы пойдете по этому пути, я бы поместил эти представления в отдельную базу данных.
источник
Есть хороший сценарий для достижения этой цели в статье SQLServerCentral:
Текущая последняя версия скрипта также доступна в виде текста здесь (stormrage.com).
Я хотел бы, чтобы был способ включить весь сценарий здесь, потому что он работает для меня. Сценарий слишком длинный, чтобы вставить его здесь.
Уведомление об авторских правах:
источник
Вы можете генерировать грубый,
CREATE TABLE
используя динамический SQL из данных вINFORMATION_SCHEMA.COLUMNS
.Если вам нужно добавить ограничения и т. Д., Вам нужно будет добавить информацию из некоторых других
INFORMATION_SCHEMA
представлений.Документация Microsoft
источник