sqlsql-serverrdbmssynonym

How can I check if the table behind a synonym exists


I'm trying to create a simple script to dump the results of a complex view out into a table for reporting. I have used synonyms to simplify tweaking the view and table names.

The idea is that the user of the script can put the name of the view they want to use as the source, and the name of the target reporting table in at the start and away they go. If the table doesn't exist then the script should create it. If the table already exists then the script should only copy the records from the view which aren't already in the table over.

The script below covers all those requirements, but I can't find a nice way to check if the table behind the synonym already exists:

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

I know I could just get the user of the script to copy the table name into the 'information_schema' line as well as into the synonym at the top, but that leaves scope for error.

I also know I could do something filthy like put the table name into a variable and blat the SQL out as a string, but that makes me feel a bit sick!

Is there a nice elegant SQL way for me to check if the table behind the synonym exists? Or a totally different way to solve to problem?


Solution

  • Not the most elegant of solutions, but you could join the sys.synonyms table to the sys.tables table to check whether the table exists.

    If the table does not exist, the join will fail and you will get 0 rows (hence IF EXISTS will be false). If the table does exist, the join will success and you will get 1 row (and 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
    

    Replace 'TargetReportingTable' with whichever synonym you wish to check.