有没有办法从临时表(表中只有一行)中选择行,到另一个表中有一些带有不同名称的列?例如:
不是Temptable
FirstName LastName Column1 Column2
------------ ------------ ----------- -----------
Joe Smith OKC TX
OtherTable
FirstName LastName Region1 Region2 Region3
------------ ------------ ----------- ----------- ----------
NULL NULL NULL NULL NULL
我需要以与TempTable中的列相同的顺序将数据复制到OtherTable中。 TempTable并不总是相同....有时它会有3列,有时只有2 ......等。如果它与OtherTable的列数不同,则剩余的“Region”列应保持为null。
最终结果应为:
OtherTable
FirstName LastName Region1 Region2 Region3
------------ ------------ ----------- ----------- ----------
Joe Smith OKC TX NULL
加上TEMPTable中的列名永远不会相同......因为在一次它将是“Column1”......下次它可能是“XXXXX1”。这就是为什么我只想复制数据......数据总是按照正确的顺序......
大声笑......这甚至有意义吗?这适用于SQL Server 2005答案 0 :(得分:1)
此代码将生成INSERT语句,以便从#TEMP INSERT到#TEMP。如果从#temp到常规表,你可以调整它以适合你的目的。
SET NOCOUNT ON
DROP Table #TempTable1
DROP Table #TempTable2
GO
DROP Function GenerateInserts
GO
Create Function GenerateInserts
(
@SourceTable VarChar (100),
@DestinationTable VarChar (100)
)
Returns VarChar (MAX)
AS
BEGIN
DECLARE @SelectString VarChar (MAX)
DECLARE @InsertString VarChar (MAX)
DECLARE @SQLString VarChar (MAX)
DECLARE @SourceColumnCount INTEGER
DECLARE @DestinationColumnCount INTEGER
DECLARE @ColumnCount INTEGER
DECLARE @Counter INTEGER
SELECT @SourceColumnCount = COUNT (*)
FROM tempdb..syscolumns
WHERE id=object_id(@SourceTable)
SELECT @DestinationColumnCount = COUNT (*)
FROM tempdb..syscolumns
WHERE id=object_id(@DestinationTable)
SET @ColumnCount = @SourceColumnCount
IF @DestinationColumnCount < @ColumnCount
SET @ColumnCount = @DestinationColumnCount
SET @Counter = 0
SET @SelectString = ' INSERT INTO ' + @DestinationTable + ' '
SET @InsertString = ' INSERT INTO ' + @DestinationTable + ' '
SET @SelectString = ''
SET @InsertString = ''
WHILE @Counter <= @ColumnCount
BEGIN
SELECT @SelectString = @SelectString + ', ' + Name
FROM TempDB..SysColumns
WHERE Id = Object_Id (@SourceTable)
AND ColOrder = @Counter
SELECT @InsertString = @InsertString + ', ' + Name
FROM TempDB..SysColumns
WHERE Id = Object_Id (@DestinationTable)
AND ColOrder = @Counter
SET @Counter = @Counter + 1
END
SET @InsertString = 'INSERT INTO ' + @DestinationTable + ' (' + STUFF ( @InsertString, 1, 2, '') + ') '
SET @SelectString = 'SELECT ' + STUFF ( @SelectString, 1, 2, '') + ' FROM ' + @SourceTable
SET @SQLString = @InsertString + '
'+ @SelectString
RETURN @SQLString
END
GO
Create Table #TempTable1
(
Col1 VarChar (10),
Col2 VarChar (10),
Col3 VarChar (10),
Col4 VarChar (10),
Col5 VarChar (10)
)
Create Table #TempTable2
(
MyCol1 VarChar (10),
MyCol2 VarChar (10),
MyCol3 VarChar (10),
MyCol4 VarChar (10),
MyCol5 VarChar (10),
MyCol6 VarChar (10)
)
SELECT dbo.GenerateInserts ('tempdb..#TempTable1', 'tempdb..#TempTable2')
是的,你可以这样做,但你必须为每种INSERT
编写不同的陈述。您必须在两个位置指定列名称 - INSERT INTO
和SELECT
如果源表和目标表中的列数相同,请执行此操作
INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, MyColumn03
FROM MyTable
这将做的是如下地图:
MyTable.MyColumn01 - &gt; Table1.Column1 MyTable.MyColumn02 - &gt; Table1.Column2 MyTable.MyColumn03 - &gt; Table1.Column3
如果Source的列数较少,则可以使用NULL值代替列名
INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03
FROM MyTable
OR 您可以使用两个列名称
INSERT INTO Table1 (Column1, Column2)
SELECT MyColumn01, MyColumn02
FROM MyTable
如果目标表的列数少于源,则必须忽略源
中的列INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03 /* MyColumn04, MyColumn05 are ignored */
FROM MyTable
答案 1 :(得分:1)
您可以使用动态SQL执行某些操作。
我建议阅读“动态SQL的诅咒和祝福 - Dealing with Dynamic Table and Column Names“如果这对你来说是新的。
示例如下。您可以改进这一点以确保源列和目标列是兼容类型或排除标识或计算列,但它应该给你一个想法。
DECLARE @SourceTable sysname
DECLARE @DestTable sysname
SET @SourceTable = '[dbo].[#TempTable]'
SET @DestTable = '[dbo].[OtherTable]'
DECLARE @DynSQL1 NVARCHAR(MAX)
DECLARE @DynSQL2 NVARCHAR(MAX)
SELECT
@DynSQL1 = ISNULL(@DynSQL1 + ',','') + QUOTENAME(sc1.name),
@DynSQL2 = ISNULL(@DynSQL2 + ',','') + QUOTENAME(sc2.name)
FROM tempdb..syscolumns sc1
JOIN syscolumns sc2
ON sc1.colorder = sc2.colorder /*Match up the columns by column order*/
WHERE sc1.id=OBJECT_ID('tempdb.' + @SourceTable) AND sc2.id=OBJECT_ID(@DestTable)
IF @@ROWCOUNT = 0
RETURN
SET @DynSQL1 = 'INSERT INTO ' + @DestTable + ' (' + @DynSQL2 + ')
SELECT ' + @DynSQL1 + ' FROM '+ @SourceTable +';'
EXEC sp_executesql @DynSQL1
答案 2 :(得分:0)
您可以指定目标表的列:
INSERT INTO OtherTable (FirstName, LastName, Region1, Region2)
SELECT FirstName, LastName, Column1, Column2 FROM TempTable;
在这个例子中,OtherTable.Region3将以NULL结尾(或者如果它具有DEFAULT值,它将使用它)。
INSERT
中的列数必须与SELECT
中的列数相匹配。因此,您必须知道TempTable中有多少列,并为插入匹配创建列列表。
但是如果你只是抛出SELECT *
,就没有办法用隐式列做到这一点。
重新评论:您可以使用INFORMATION_SCHEMA
查询表格中的计数和列名称。
SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'tempdb' AND TABLE_SCHEMA = 'MySchema'
AND TABLE_NAME LIKE 'MyTempTable%';
然后,您将编写应用程序代码,以根据此information_schema查询的结果创建SQL INSERT...SELECT
语句。
注意:通过information_schema查询临时表需要special handling。