5

複雑なビューの結果をレポート用のテーブルにダンプする簡単なスクリプトを作成しようとしています。ビュー名とテーブル名の微調整を簡単にするために同義語を使用しました。

スクリプトのユーザーは、ソースとして使用するビューの名前と、ターゲットレポートテーブルの名前を最初と最後に入力できるという考え方です。テーブルが存在しない場合は、スクリプトで作成する必要があります。テーブルがすでに存在する場合、スクリプトは、テーブルにまだ存在していないレコードのみをビューからコピーする必要があります。

以下のスクリプトはこれらすべての要件をカバーしていますが、同義語の背後にあるテーブルがすでに存在するかどうかを確認するための良い方法を見つけることができません。

CREATE SYNONYM SourceView FOR my_view
CREATE SYNONYM TargetReportingTable FOR my_table

-- Here's where I'm having trouble, how do I check if the underlying table exists?
IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_name = TargetReportingTable) = 0
  BEGIN
    -- Table does not exists, so insert into.
    SELECT * INTO TargetReportingTable FROM SourceView
  END
ELSE
  BEGIN
    -- Table already exists so work out the last record which was copied over
    -- and insert only the newer records.
    DECLARE @LastReportedRecordId INT;
    SET @LastReportedRecordId = (SELECT MAX(RecordId) FROM TargetReportingTable)
    INSERT INTO TargetReportingTable SELECT * FROM SourceView WHERE RecordId > @LastReportedRecordId
  END

DROP SYNONYM SourceView
DROP SYNONYM TargetReportingTable

スクリプトのユーザーにテーブル名を「information_schema」行と上部の同義語にコピーさせることができることはわかっていますが、エラーの余地があります。

また、テーブル名を変数に入れてSQLを文字列として公開するなど、不潔なことをすることもできますが、それでは少し気分が悪くなります。

同義語の背後にあるテーブルが存在するかどうかを確認するための優れたエレガントなSQLの方法はありますか?または、問題を解決するためのまったく異なる方法ですか?

4

6 に答える 6

3

最も洗練されたソリューションではありませんが、sys.synonymsテーブルをテーブルに結合してsys.tables、テーブルが存在するかどうかを確認できます。

テーブルが存在しない場合、結合は失敗し、0行が取得されます(したがってIF EXISTS、falseになります)。テーブルが存在する場合、結合は成功し、1行(およびtrue)になります。

IF EXISTS(  SELECT  *
              FROM  sys.synonyms s
                INNER JOIN sys.tables t ON REPLACE(REPLACE(s.base_object_name, '[', ''), ']', '') = t.name
              WHERE s.name = 'TargetReportingTable')
BEGIN
    -- Does exist
END
ELSE
BEGIN
    -- Does not exist
END

'TargetReportingTable'確認したい同義語に置き換えます。

于 2013-03-26T15:00:17.997 に答える
2

シノニムが別のデータベースを参照している場合、上記のソリューションは機能しませんでした。最近、特定のデータベースオブジェクトのアクセス許可を表示するのに役立つ関数[fn_my_permissions]を発見したので、これは次のように使用できると思います。

IF EXISTS
(
select *
from sys.synonyms sy
cross apply fn_my_permissions(sy.base_object_name, 'OBJECT')
WHERE sy.name = 'TargetReportingTable'
)
print 'yes - I exist!'
于 2015-04-09T13:45:31.073 に答える
2

パーティーの後半に、私はあなたの存在をテストしてSynonymsあなたと共有するためのクエリを作成しました。

DECLARE @Synonyms table
(
    ID int identity(1,1),
    SynonymsDatabaseName sysname,
    SynonymsSchemaName sysname,
    SynonymsName sysname,
    DatabaseName nvarchar(128),
    SchemaName nvarchar(128),
    ObjectName nvarchar(128),

    Remark nvarchar(max),
    IsExists bit default(0)
)

INSERT @Synonyms (SynonymsDatabaseName, SynonymsSchemaName, SynonymsName, DatabaseName, SchemaName, ObjectName)
SELECT 
    DB_NAME() AS SynonymsDatabaseName,
    SCHEMA_NAME(schema_id) AS SynonymsSchemaName,
    name AS SynonymsName,
    PARSENAME(base_object_name,3) AS DatabaseName,
    PARSENAME(base_object_name,2) AS SchemaName,
    PARSENAME(base_object_name,1) AS ObjectName
FROM sys.synonyms


SET NOCOUNT ON

DECLARE @ID int = 1, @Query nvarchar(max), @Remark nvarchar(max)

WHILE EXISTS(SELECT * FROM @Synonyms WHERE ID = @ID)
BEGIN

    SELECT 
        @Query = 'SELECT @Remark = o.type_desc FROM [' + DatabaseName + '].sys.objects o INNER JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE s.name = ''' + SchemaName + ''' AND o.name = ''' + ObjectName + ''''
    FROM @Synonyms WHERE ID = @ID

    EXEC sp_executesql @Query, N'@Remark nvarchar(max) OUTPUT', @Remark OUTPUT;

    UPDATE @Synonyms SET IsExists = CASE WHEN @Remark IS NULL THEN 0 ELSE 1 END, Remark = @Remark WHERE ID = @ID

    SELECT @ID += 1, @Remark = NULL
END

SELECT * FROM @Synonyms
于 2015-10-16T09:33:08.060 に答える
1

これは動的SQLで実行できます。

-- create synonym a for information_schema.tables
create synonym a for b

declare @exists int = 1;
begin try
    exec('select top 0 * from a');
end try
begin catch
    set @exists = 0;
end catch
select @exists;

シノニム参照はコンパイル時にキャッチされるため、これは非動的SQLでは機能しません。tryこれは、コードがメッセージで失敗し、 /catchブロックによってキャッチされないことを意味します。動的SQLでは、ブロックがエラーをキャッチします。

于 2013-03-26T14:49:16.753 に答える
0

SQL Serverで使用可能なObject_Id関数を使用して、データベースにシノニムが存在するかどうかをテストできます。

IF OBJECT_ID('YourDatabaseName..YourSynonymName') IS NOT NULL
    PRINT 'Exist SYNONYM'
ELSE 
    PRINT 'Not Exist SYNONYM'
于 2017-07-14T17:37:09.523 に答える
0

別のより簡単な解決策:

IF (EXISTS (SELECT * FROM sys.synonyms WHERE NAME ='mySynonymName'))
BEGIN
    UPDATE mySynonymName
    SET [Win] = 1
END

この場合、最初にデータベースのセットアップを行います。最初にデータベース(database1)のすべてのシノニムを削除してから、SPROCを実行して、宛先データベース(database2)のすべてのテーブルのシノニムを作成します。database1の一部のSPROCSは、DB2のテーブルを呼び出します。テーブルがDB2に存在しない場合、SPROCは失敗します。表がDB2に存在しない場合、シノニムはデータベースのセットアップ時に自動的に作成されません。したがって、上記を使用して同義語が存在するかどうかを確認し、同義語が存在しない場合はSPROCのその部分をスキップします。

于 2019-05-29T20:56:49.703 に答える