EDIT:データベース名を簡単にするために変更されているSQL更新が
私は別のデータベースにいくつかの主要な生産のテーブルの静的コピーを更新するための場所にいくつかの動的SQLを取得しようとしている(sql2008r2 )。ここでの目標は、生産データベースがほぼ毎日更新されるため、特定の期間、(静的なデータベースからの)データの一貫した配布を可能にすることです。
私はCURSOR
を使用して、 '静的'データベースにコピーされるオブジェクトを含むテーブルをループします。
1)、
EXEC()
は限定的なものと思われるので、私は、私はEXEC sp_executesql
を使用する必要があるだろうと信じているが、私はそれをすべてのまわりで私の頭を取得して少し問題を抱えています。追加の余分として2)、すべての可能で、私はまた、特定のテーブルの一部の列を除外したい場合(構造は「静的」データベースに多少異なります)
prod
の表は、その頻繁に変更されませんが、私はこのやや「未来の証明」をしたいのですが(可能ならば!)と(代わりに
SELECT * FROM ...
を使用しての)各オブジェクトに対して
INFORMATION_SCHEMA.COLUMNS
から列名を抽出します私は他の記事で読んだものから、
ここで私は何ですこれまでのところあります。 @colnames
がNULLを返すため、@sql
がNULLを返します。
解決策が見つかるかもしれない人に私を導くことができますか?
このコードに関する助言や助けをいただければ幸いです。
CREATE PROCEDURE sp_UpdateRefTables
@debug bit = 0
AS
declare @proddbname varchar(50),
@schemaname varchar(50),
@objname varchar(150),
@wherecond varchar(150),
@colnames varchar(max),
@sql varchar(max),
@CRLF varchar(2)
set @wherecond = NULL;
set @CRLF = CHAR(10) + CHAR(13);
declare ObjectCursor cursor for
select databasename,schemaname,objectname
from Prod.dbo.ObjectsToUpdate
OPEN ObjectCursor ;
FETCH NEXT FROM ObjectCursor
INTO @proddbname,@schemaname,@objname ;
while @@FETCH_STATUS=0
begin
if @objname = 'TableXx'
set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol1'''
if @objname = 'TableYy'
set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol2'''
--extract column names for current object
select @colnames = coalesce(@colnames + ',', '') + QUOTENAME(column_name)
from Prod.INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = + QUOTENAME(@objname,'') + isnull(@wherecond,'')
if @debug=1 PRINT '@colnames= ' + isnull(@colnames,'null')
--replace all data for @objname
[email protected] is used as schema name in Static database
SELECT @sql = 'TRUNCATE TABLE ' + @proddbname + '.' + @objname + '; ' + @CRLF
SELECT @sql = @sql + 'INSERT INTO ' + @proddbname + '.' + @objname + ' ' + @CRLF
SELECT @sql = @sql + 'SELECT ' + @colnames + ' FROM ' + @proddbname + '.' + @schemaname + '.' + @objname + '; '
if @debug=1 PRINT '@sql= ' + isnull(@sql,'null')
EXEC sp_executesql @sql
FETCH NEXT FROM ObjectCursor
INTO @proddbname,@schemaname,@objname ;
end
CLOSE ObjectCursor ;
DEALLOCATE ObjectCursor ;
P.S.私はSQLインジェクションについて読んだことがありますが、これは内部の管理タスクなので、私はここで安全だと推測しています!これに関するアドバイスもありがとうございます。
多くのことに感謝します。
多くのおかげで、私はこれを試してみましょう。私はINFORMATION_SCHEMA.Columnsが一番良いと思いましたが、答えに応じてsys.columnsに変更します。またIFをCASE文に変更しなければならないことも知っていましたが、「STUFF」を認識しておらず、これを見ていきます! :) – MarkusBee
STUFFは先頭の '、'を取り除いています。これは、クエリ内の 'COALESCE'連結のすべての処理よりもずっと簡単です。 –
あなたの答えは魅力的でした。どうもありがとう。私は問題を複雑に過ぎていたと思う。 私はCOALESCEの個人的な好みがあります - 私はもう少しエレガントで、この例ではSTUFFステートメントの必要性を軽減しています。しかし私はSTUFFの他の用途を見ることができるので、これを念頭に置いておく。 :) – MarkusBee