2013-03-26 17 views
5

Próbuję utworzyć prosty skrypt, aby zrzucić wyniki kompleksowego widzenia się do tabeli raportowania. Użyłem synonimów, aby uprościć dostosowywanie nazw widoków i tabel.Jak mogę sprawdzić, czy tabela za synonim istnieje

Pomysł polega na tym, że użytkownik skryptu może umieścić nazwę widoku, z którego chce korzystać jako źródło, oraz nazwę docelowej tabeli raportowania na początku i na końcu, z której pochodzą. Jeśli tabela nie istnieje, skrypt powinien ją utworzyć. Jeśli tabela już istnieje, skrypt powinien kopiować tylko rekordy z widoku, które nie znajdują się już w tabeli.

Skrypt poniżej obejmuje wszystkie te wymagania, ale nie mogę znaleźć dobry sposób, aby sprawdzić, czy tabela za synonim już istnieje:

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 

wiem, może po prostu dostać użytkownikowi skryptu aby skopiować nazwę tabeli do wiersza "information_schema", a także do synonimu u góry, ale pozostawia pole do błędu.

wiem też mogę coś zrobić brudny jak umieścić nazwę tabeli do zmiennej i blat SQL jako ciąg, ale to sprawia, że ​​czuję się trochę chory!

Czy istnieje ładny elegancki SQL dla mnie sposób, by sprawdzić, czy tabela za synonim istnieje? Lub zupełnie inny sposób rozwiązania problemu?

+2

proszę oznaczyć swoje pytanie ze szczególnymi RDBMS, nie tylko „sql” – Barmar

+1

Niestety, błąd rekrut. Dziękuję za edycję. – Tom

+0

Czy możemy założyć punkty synonimów w bazie danych, w której znajduje się synonim, czy może wskazywać na inne pliki db? –

Odpowiedz

3

Nie najmądrzejszy z rozwiązań, ale można dołączyć do tabeli sys.synonyms do tabeli sys.tables, aby sprawdzić, czy tabela istnieje.

Jeśli tabela nie istnieje, dołącz zawiedzie, a dostaniesz 0 wiersze (stąd IF EXISTS będzie false). Jeśli tabela nie istnieje, sukces dołączy, a dostaniesz 1 wiersz (i prawdziwe):

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 

Wymień 'TargetReportingTable' z dowolny synonim chcesz sprawdzić.

+0

Dzięki, że działa dobrze. Chociaż, jak mówisz, nie jest to najpiękniejsze zapytanie, oznacza to przynajmniej, że użytkownik skryptu nie musi wklejać nazwy tabeli w wielu miejscach. – Tom

+1

Zamiast używania 'REPLACE', bardziej niezawodnym sposobem uzyskania informacji o tabeli i schemacie byłoby użycie funkcji' PARSENAME'. Zobacz: https://msdn.microsoft.com/en-us/library/ms188006.aspx – Nathan

1

Można to zrobić z dynamicznym 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; 

To nie działa non-dynamicznego SQL, ponieważ odwołanie synonim jest złapany w czasie kompilacji. Oznacza to, że kod po prostu zawiedzie z komunikatem i nie jest przechwytywany przez blok try/catch. W przypadku dynamicznego SQL blok przejmuje błąd.

+0

Dzięki. Nie bardzo rozumiem, jak to pomaga. To nie jest tabela informacji_schematowa Próbuję uzyskać nazwę, to prawdziwy stół za synonimem (ten o nazwie "TargetReportingTable" w powyższym skrypcie). Czy coś przeoczyłem? – Tom

+0

@ Tom. . . To tylko przykłady, które pokazują, że kod działa. W testowanej bazie danych 'b' nie istnieje, więc' 0' zostaje przypisane do '@ exists'. Po ustawieniu na istniejącą tabelę przypisywane jest '1'. –

2

powyższych rozwiązań nie działa dla mnie, jeśli synonim odwołuje innej bazy danych. Niedawno odkryto funkcję [fn_my_permissions], który jest przydatny do pokazania uprawnień dla określonego obiektu bazy danych, więc postać to może być używane w następujący sposób:

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!' 
+0

Musiałem użyć "sy.sname" w mojej wersji Oracle. Również nie znalazłem zastosowania krzyżowego niezbędnego dla moich celów – Mangusta

1

późno do partii, Stworzyłem zapytanie do wypróbowania istnienie Synonyms i podzielić się z Wami.

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 
0

można przetestować jeśli Synonim istnieje w bazie danych przy użyciu funkcji dostępna object_id w SQL Server

IF OBJECT_ID('YourDatabaseName..YourSynonymName') IS NOT NULL 
    PRINT 'Exist SYNONYM' 
ELSE 
    PRINT 'Not Exist SYNONYM' 
Powiązane problemy