动态生成带有来自另一个表的数据的insert语句

时间:2015-07-05 13:07:18

标签: sql-server sql-server-2008 tsql stored-procedures sql-server-2008-r2

我想创建存储过程并动态生成表的insert语句。存储过程的输入参数应为schema, table name, @col1, @col2, ..., @colN。该存储过程应该从另一个服务器获取1个随机记录,并且基于该记录应该生成INSERT语句。 @col1, @col2, ..., @colN参数是可选的,以防您想要用您需要的值覆盖原始值。

插入记录看起来应该是这样的:

INSERT INTO schema_name.table_name VALUES (
col1,
col2,
...,
colN)
VALUES (
COALESCE(@col1, 'col1_value'),
COALESCE(@col2, 'col2_value'),
...,
COALESCE(@colN, 'colN_value')
);

目前我无法实现如何获取真实数据并将其置于声明中。我已经做的是:

CREATE PROCEDURE dbo.GenerateSampleDataInsertSP
    @SchemaName VARCHAR(255),
    @TableName VARCHAR(255)
AS
SET NOCOUNT ON;
DECLARE @sql VARCHAR(MAX) = '',
    @columns VARCHAR(MAX) = '',
    @columnsWithCoalesce VARCHAR(MAX) = '';

SELECT  c.name
INTO    #column
FROM    sys.tables t
        JOIN sys.schemas s ON s.schema_id = t.schema_id
        JOIN sys.columns c ON c.object_id = t.object_id
        JOIN sys.types tt ON c.system_type_id = tt.system_type_id
WHERE   t.name = @TableName
        AND s.name = @SchemaName
        AND tt.name NOT IN ( 'timestamp' );


SET @columns = NULL; 
SELECT  @columns = ISNULL(@columns + ', ', '') + name
FROM    #column;

SET @sql = 'SELECT TOP 1 ' + @columns + ' FROM AnotherDatabase.' + @SchemaName + '.' + @TableName + ' ORDER BY NEWID();';



SET @sql = 'INSERT INTO [' + @SchemaName + '].[' + @TableName + '] (' + @columns + ') VALUES ();';

SELECT  @sql;

我不关心理想的代码或解决方案。我需要结果,那就是它。

更新:

- 示例#1

USE tempdb
GO

/*CREATE PROCEDURE dbo.GenerateSampleDataInsertSP ...*/

CREATE TABLE dbo.Employee (ID INT, EmployeeName VARCHAR(255));
INSERT INTO dbo.Employee VALUES (1, 'John Smith');

EXEC dbo.GenerateSampleDataInsertSP @SchemaName = 'dbo', @TableName = 'Employees';

------------------------ EXPECTED OUTPUT OF THE PROCEDURE (NOT THE ACTION, BUT PLAIN TEXT) ------------------

INSERT INTO dbo.Employee
(
 ID,
 EmployeeName
)
VALUES
(
 COALESCE(@ID, '1'), 
 COALESCE(@EmployeeName, 'John Smith') 
);

- 示例#2

USE tempdb
GO

/*CREATE PROCEDURE dbo.GenerateSampleDataInsertSP ...*/

CREATE TABLE dbo.Orders (ID INT, OrderNbr VARCHAR(10), OrderDate DATE, CustomerID ID);

INSERT INTO dbo.Orders VALUES (7, '12345678', GETDATE(), 1024);

EXEC dbo.GenerateSampleDataInsertSP @SchemaName = 'dbo', @TableName = 'Orders';

------------------------ EXPECTED OUTPUT OF THE PROCEDURE (NOT THE ACTION, BUT PLAIN TEXT) ------------------

INSERT INTO dbo.Orders 
(
  ID,
  OrderNbr,
  OrderDate,
  CustomerId
)
VALUES
(
  COALESCE(@ID, '7'),
  COALESCE(@OrderNbr,'12345678'),
  COALESCE(@OrderDate, '2015-07-05'),
  COALESCE(@CustomerId, '1024')
);

1 个答案:

答案 0 :(得分:0)

好的,我会回答我自己的问题。正如我所说,我不关心代码的美感和性能,我只需要结果,所以任何提供更优雅解决方案的人都会被接受为解决方案。这是代码:

CREATE PROCEDURE dbo.GenerateSampleDataInsertSP
    @SchemaName VARCHAR(255),
    @TableName VARCHAR(255)
AS
SET NOCOUNT ON;

IF EXISTS ( SELECT  name
            FROM    tempdb.sys.tables
            WHERE   name LIKE '%##record%' )
BEGIN
    DROP TABLE ##record;
END;
DECLARE @sql VARCHAR(MAX) = '',
    @columns VARCHAR(MAX) = '',
    @columnsWithCoalesce VARCHAR(MAX) = '';

SELECT  c.name
INTO    #column
FROM    sys.tables t
        JOIN sys.schemas s ON s.schema_id = t.schema_id
        JOIN sys.columns c ON c.object_id = t.object_id
        JOIN sys.types tt ON c.system_type_id = tt.system_type_id
WHERE   t.name = @TableName
        AND s.name = @SchemaName
        AND tt.name NOT IN ( 'timestamp' );


SET @columns = NULL; 
SELECT  @columns = ISNULL(@columns + ', ', '') + name
FROM    #column;

SET @sql = 'SELECT TOP 1 ' + @columns + ' INTO ##record FROM AnotherDataBase.' + @SchemaName + '.' + @TableName + ' ORDER BY NEWID();';

EXEC (@sql);

SET @sql = 'INSERT INTO [' + @SchemaName + '].[' + @TableName + '] (' + @columns + ') VALUES (';

DECLARE @columnsCur CURSOR, @ColumnName VARCHAR(255), @tmpValue VARCHAR(MAX), @sqlCommand nvarchar(1000);
SET @columnsCur = CURSOR FOR
SELECT name
FROM #column;
OPEN @columnsCur;
FETCH NEXT
FROM @columnsCur INTO @ColumnName;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sqlCommand = 'SELECT @value=CAST(' + @ColumnName + ' AS VARCHAR(MAX)) FROM ##record;'
    EXECUTE sp_executesql @sqlCommand, N'@value VARCHAR(MAX) OUTPUT', @value=@tmpValue OUTPUT
    SET @sql = @sql + 'COALESCE(@'+ @ColumnName +', ''' + @tmpValue + '''),';
    FETCH NEXT
FROM @columnsCur INTO @ColumnName;
END;
CLOSE @columnsCur;
DEALLOCATE @columnsCur;


SET @sql = @sql + ');'

SET @sql = REPLACE(@sql, ',);', ');');

SELECT  @sql;

GO