2

すべてのテーブルから別のスキーマの同じ名前のテーブルにデータをコピーしようとした経験を共有することにしました。私の経験は、サポートされていない、率直に言って制限されsp_MSforeachtableた .

目的:データベース内のすべてのテーブルから、スキーマが異なる同じ名前のテーブルにデータをコピーする

についての簡単なメモ sp_MSforeachtableSO でこのストアド プロシージャについて質問するほとんどの場合、サポートされていない機能を使用するべきではないという回答が返ってきます。これは単に真実ではありません。私たちがすべきでないことは、サポートされていない機能に基づいてプラクティスや設計上の決定を行うことです。しかし、ある特定の時点で、サポートされていない機能が存在し、その時点で必要な機能を 1 回限りのスタイルで実行する場合は、運が良かったと考えて、ぜひそれを使用し、予期しない動作に注意してください。このような機能を使用する場合は、出力がすばやく簡単に検証できる単純な操作に固執するのが最善です。

そうは言っても、また にはいくつかの実際の制限があるため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 に答える