Comments 5
Спасибо за статью. Хотел бы обратить Ваше внимание на несколько нюансов (insertRandomData).
Системное представление sys.all_objects содержит в себе и пользовательские и системные объекты. А поскольку фильтром Вы оставляете только пользовательские таблицы (type = 'U'), то целесообразно делать выборку из sys.objects. За счет этого Вы получите более эффективный план выполнения.
Также меня немного настораживает соединение с systypes. Возможно Вы хотели сделать соединение по user_type_id. В противном случае, возможна ситуация когда можно получить дублирование строк.
В общем, мой вариант Вашего запроса:
Системное представление sys.all_objects содержит в себе и пользовательские и системные объекты. А поскольку фильтром Вы оставляете только пользовательские таблицы (type = 'U'), то целесообразно делать выборку из sys.objects. За счет этого Вы получите более эффективный план выполнения.
Также меня немного настораживает соединение с systypes. Возможно Вы хотели сделать соединение по user_type_id. В противном случае, возможна ситуация когда можно получить дублирование строк.
В общем, мой вариант Вашего запроса:
SELECT c.column_id
, c.name
, TYPE_NAME(c.user_type_id)
, c.max_length
FROM sys.objects o
JOIN sys.columns c ON c.[object_id] = o.[object_id]
WHERE o.[type] = 'U'
AND TYPE_NAME(c.system_type_id) != 'sysname'
AND o.name LIKE @childTableName
ORDER BY c.column_id;
0
www.mssqltips.com/sqlservertip/2190/generating-sql-server-test-data-with-visual-studio-2010/
www.red-gate.com/products/sql-development/sql-data-generator/
www.datanamic.com/datagenerator-for-mssql/
Зачастую пишем через шарп — удобнее…
Таблица на 50 млн строк (50 колонок) генерируется порядка 5 минут.
А так можно использовать оффсеты, фетч и CTE для скоростей.
Используйте временную таблицу и вставляйте без Values.
INSERT INTO tbl
SELECT * FROM #tbl
Либо через CTE и даты формируйте блоки данных нужной длины.
Либо вставляйте по 100 строк хотя бы (блочный принцип).
INSERT INTO Production.UnitMeasure
VALUES (N'FT2', N'Square Feet ', '20080923'),
(N'Y', N'Yards', '20080923'),
(N'Y3', N'Cubic Yards', '20080923');
Ну и если можно вместо курсора использовать WHILE — используйте.
www.red-gate.com/products/sql-development/sql-data-generator/
www.datanamic.com/datagenerator-for-mssql/
Зачастую пишем через шарп — удобнее…
Таблица на 50 млн строк (50 колонок) генерируется порядка 5 минут.
А так можно использовать оффсеты, фетч и CTE для скоростей.
Используйте временную таблицу и вставляйте без Values.
INSERT INTO tbl
SELECT * FROM #tbl
Либо через CTE и даты формируйте блоки данных нужной длины.
Либо вставляйте по 100 строк хотя бы (блочный принцип).
INSERT INTO Production.UnitMeasure
VALUES (N'FT2', N'Square Feet ', '20080923'),
(N'Y', N'Yards', '20080923'),
(N'Y3', N'Cubic Yards', '20080923');
Ну и если можно вместо курсора использовать WHILE — используйте.
0
вот можно эту доработать dba.stackexchange.com/questions/19938/a-script-to-insert-dummy-data-in-all-tables-of-database,
А вот так можно вычленить сначала справочники без ключей.
ALTER PROCEDURE [dbo].[FillRandomData]
@DatabaseName NVARCHAR(50) = 'TestData'
AS
BEGIN
DECLARE sql NVARCHAR(512) = 'USE [' + @DatabaseName + '];' + ' SELECT name, object_id FROM sys.tables WHERE name <> ''sysdiagrams'' AND type = ''U'''
DECLARE @tblData TABLE(name nvarchar(255), object_id int)
DECLARE @TablesWithFK TABLE(name nvarchar(255), object_id int)
DECLARE @TablesWithoutFK TABLE(name nvarchar(255), object_id int)
INSERT INTO @tblData
EXEC (sql)
INSERT INTO @TablesWithFK
SELECT t.name, t.object_id
FROM @tblData t
LEFT JOIN sys.foreign_key_columns fc ON fc.referenced_object_id = t.object_id
WHERE fc.constraint_column_id IS NULL
GROUP BY t.name, t.object_id
INSERT INTO @TablesWithoutFK
SELECT t.name, t.object_id
FROM @tblData t
LEFT JOIN sys.foreign_key_columns fc ON fc.referenced_object_id = t.object_id
WHERE fc.constraint_column_id IS NOT NULL
GROUP BY t.name, t.object_id
DECLARE cur CURSOR READ_ONLY FOR SELECT name FROM @TablesWithoutFK
DECLARE name NVARCHAR(50)
OPEN cur
FETCH NEXT FROM cur INTO name
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
PRINT name
END
FETCH NEXT FROM cur INTO name
END
CLOSE cur
DEALLOCATE cur
END
А вот так можно вычленить сначала справочники без ключей.
ALTER PROCEDURE [dbo].[FillRandomData]
@DatabaseName NVARCHAR(50) = 'TestData'
AS
BEGIN
DECLARE sql NVARCHAR(512) = 'USE [' + @DatabaseName + '];' + ' SELECT name, object_id FROM sys.tables WHERE name <> ''sysdiagrams'' AND type = ''U'''
DECLARE @tblData TABLE(name nvarchar(255), object_id int)
DECLARE @TablesWithFK TABLE(name nvarchar(255), object_id int)
DECLARE @TablesWithoutFK TABLE(name nvarchar(255), object_id int)
INSERT INTO @tblData
EXEC (sql)
INSERT INTO @TablesWithFK
SELECT t.name, t.object_id
FROM @tblData t
LEFT JOIN sys.foreign_key_columns fc ON fc.referenced_object_id = t.object_id
WHERE fc.constraint_column_id IS NULL
GROUP BY t.name, t.object_id
INSERT INTO @TablesWithoutFK
SELECT t.name, t.object_id
FROM @tblData t
LEFT JOIN sys.foreign_key_columns fc ON fc.referenced_object_id = t.object_id
WHERE fc.constraint_column_id IS NOT NULL
GROUP BY t.name, t.object_id
DECLARE cur CURSOR READ_ONLY FOR SELECT name FROM @TablesWithoutFK
DECLARE name NVARCHAR(50)
OPEN cur
FETCH NEXT FROM cur INTO name
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
PRINT name
END
FETCH NEXT FROM cur INTO name
END
CLOSE cur
DEALLOCATE cur
END
0
Для того, чтобы не тратить время и нервы на генерацию тестовых данных, можно воспользоваться замечательным инструментом — dbForge Data Generator for SQL Server. Этот инструмент имеет более 200 встроеных генераторов на все слуаи жизни. Важным фактом является то, что он генерирует т.н. meaningful тестовые данные, т.е. не рандомные стринги и инты, а осознанные данные с поддержкой всех типов констреинтов. Каждый из генераторов очень гибко настраивается под индивидуальные нужды. MUST HAVE TOOL для DB Dev и QA.
+1
Sign up to leave a comment.
Как заполнить базу данных MS SQL разнородными случайными данными или 17 часов ожидания