无论 SQL Server 中的列名如何,都将整行选择到另一个表中

发布于 2024-09-11 00:18:33 字数 1137 浏览 6 评论 0原文

有没有办法从临时表(表只有一行)中选择行到另一个具有不同名称的列的表中?例如:

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”列应保持为空。

最终结果应该是:

OtherTable

FirstName       LastName         Region1       Region2         Region3
------------    ------------     -----------   -----------     ----------
Joe              Smith             OKC           TX               NULL

另外,TEMPTable 中的列名称永远不会相同...因为一次它会是“Column1”...下一次可能是“XXXXX1” 。这就是为什么我只想复制数据...数据将始终按正确的顺序...

哈哈...这有意义吗?这是针对 SQL Server 2005

Is there a way to select the row from a temp table (table has only one row anyway), into another table that has some columns with differenet names? For example:

TempTable

FirstName        LastName          Column1       Column2
------------    ------------     -----------   -----------
Joe              Smith             OKC           TX

OtherTable

FirstName       LastName          Region1        Region2        Region3
------------    ------------     -----------   -----------     ----------
NULL              NULL             NULL           NULL           NULL

I need to copy the data, in the same order as the columns from TempTable into OtherTable. TempTable will not always be the same....as in sometimes it will have 3 columns, sometimes just 2...etc. If it does not have the same number of columns as OtherTable, the the remaining "Region" columns should stay null.

The end result should be:

OtherTable

FirstName       LastName         Region1       Region2         Region3
------------    ------------     -----------   -----------     ----------
Joe              Smith             OKC           TX               NULL

PLUS the column names in TEMPTable will NEVER be the same...as in one time it will be "Column1"...the next time it could be "XXXXX1". That's why I just want to copy data only...the data will always be in the correct order...

LOL...does this even make sense? This is for SQL Server 2005

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

囚我心虐我身 2024-09-18 00:18:33

编辑........添加动态SQL生成

此代码将生成INSERT语句以从#TEMP插入#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 INTOSELECT


如果源表和目标表中的列数相同,请执行以下

INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, MyColumn03
FROM MyTable 

操作要做的就是映射如下:

MyTable.MyColumn01 ->表1.Column1
MyTable.MyColumn02 ->表1.列2
MyTable.MyColumn03 -> Table1.Column3


如果源表的列数较少,则可以使用 NULL 值代替列名

INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03
FROM MyTable 

或者,您可以只使用两个列名

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 

EDIT ........ Dynamic SQL Generation added

This code will generate INSERT statements to INSERT from #TEMP into #TEMP. You can tweak it to suit your purpose if you are going from #temp to regular tables.

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')



OLD ANSWER

Yes you can do this but you have to write different statements for each type of INSERT. You do have to specify column names in both places - the INSERT INTO and the SELECT


If you have the same number of columns in your Source and Destination tables, do this

INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, MyColumn03
FROM MyTable 

What this will do is map as follows:

MyTable.MyColumn01 -> Table1.Column1
MyTable.MyColumn02 -> Table1.Column2
MyTable.MyColumn03 -> Table1.Column3


If the Source has less columns, you can use a NULL value in place of the column name

INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03
FROM MyTable 

OR you can just use two column names

INSERT INTO Table1 (Column1, Column2)
SELECT MyColumn01, MyColumn02
FROM MyTable 

If the destination table has less columns than the source, then you have to ignore columns from the source

INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03 /* MyColumn04, MyColumn05 are ignored */
FROM MyTable 
垂暮老矣 2024-09-18 00:18:33

您可以使用动态 SQL 做一些事情。

我建议阅读“动态 SQL 的诅咒和祝福 -
如果您不熟悉的话,处理动态表和列名”。

示例如下。您可以改进这一点,以确保源列和目标列具有兼容的类型,或者排除身份列或计算列,但它应该给您一个想法。

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

You could do something with dynamic SQL.

I recommend reading "The Curse and Blessings of Dynamic SQL -
Dealing with Dynamic Table and Column Names" if this is new to you.

Example follows. You could improve this to be sure that source and destination columns are of compatible types or to exclude identity or computed columns for example but it should give you an idea.

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
翻了热茶 2024-09-18 00:18:33

您可以指定目标表的列:

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 查询临时表需要 特殊处理

You can specify the columns of the target table:

INSERT INTO OtherTable (FirstName, LastName, Region1, Region2)
  SELECT FirstName, LastName, Column1, Column2 FROM TempTable;

In this example, OtherTable.Region3 will end up NULL (or if it has a DEFAULT value, it'll use that).

The count of columns in the INSERT must match the count of columns in the SELECT. So you must know how many columns in TempTable and make the list of columns for the insert match.

But there's no way to do it with implicit columns, if you're just throwing SELECT * around.


Re your comment: You can use the INFORMATION_SCHEMA to query the count and the names of the columns in the table.

SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'tempdb' AND TABLE_SCHEMA = 'MySchema'
  AND TABLE_NAME LIKE 'MyTempTable%';

Then you would write application code to create your SQL INSERT...SELECT statement based on the results from this information_schema query.

Note: Querying temp tables through the information_schema requires special handling.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文