2

我决定分享我尝试将所有表中的数据复制到不同模式中的同名表中的经验。我相信我的经验可以帮助其他人在不使用不受支持且坦率有限的sp_MSforeachtable.

目标:将数据库中所有表的数据复制到具有不同架构的同名表

关于 sp_MSforeachtable. 大多数时候,当人们在 SO 中询问有关此存储过程的问题时,会有一些回复或另一种说法是我们不应该使用不受支持的功能。这根本不是真的,我们不应该做的是基于不受支持的功能的实践和设计决策,主要是因为它们可能会消失。但是在某个特定的时间点,如果存在不受支持的功能,并且完全符合我们当时需要做的事情,一次性的风格,那么就认为自己很幸运,一定要使用它,只是要小心意外行为。使用此类功能时,最好坚持简单的操作,其输出可以快速轻松地验证。

话虽如此,而且由于存在一些实际限制sp_MSforeachtable,我提出了一种不同但不太复杂的方法来针对我们数据库中的所有(或特定)表执行语句,并且我以我的问题为例。

4

1 回答 1

2

我经常通过生成返回语句的查询来解决这个问题,然后将这些语句复制粘贴到一个新的查询窗口中并执行它们。我喜欢这种方法,因为我在执行语句之前看到了我的语句,并且还可以使用解析器快速识别它们的问题。考虑到这一点,这是我的查询:

SELECT DISTINCT ''
    + ' INSERT INTO ' + 'dbo.' + QUOTENAME(name)
    + ' (' + dbo.COLUMN_NAMES('dbo', name) + ')'
    + ' SELECT ' + dbo.COLUMN_NAMES('dbo', name)
    + ' FROM ' + 'db_owner.' + QUOTENAME(name)
FROM sys.tables
-- add your own WHERE clauses to only execute against specific tables

就是这么简单。这将返回一个 INSERT INTO ... SELECT FROM... 语句列表,我可以简单地将其复制粘贴到一个新的查询窗口中。

如果您想知道为什么不只使用 SELECT *,那仅仅是因为如果您的表有 ID 列,那么您将需要显式命名这些列并在前后添加 SET_IDENTITY 语句。

COLUMN_NAMES 函数是一个非常不言自明的函数,它返回指定表的逗号分隔列名:

CREATE FUNCTION COLUMN_NAMES
(
    @tableschema VARCHAR(MAX),
    @tablename VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN

RETURN (
    REPLACE(
        (SELECT QUOTENAME(COLUMN_NAME) AS 'data()'
         FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_SCHEMA=@tableschema AND TABLE_NAME=@tablename ORDER BY ORDINAL_POSITION FOR XML PATH('')),
         ' ',', '))

END
GO
于 2012-11-02T10:56:16.017 回答