1

I haven't being programming in a while and I am stuck on a problem. I am building a small application that you can select one of the 32 counties of Ireland from.

In my database called BlackCorsetDatabase, I want to use only stored procedures.

I want to check to see if the table is connected before I try to write to the database first.

This is the code that I have written so far:

CREATE PROCEDURE [dbo].[CheckTableCountyExists]
    (@TableExists BIT)
AS
    IF EXISTS (SELECT * 
               FROM BlackCorsetDatabase 
               WHERE TABLE_NAME = 'County')
    BEGIN
        PRINT 'Table Exists'
        @TableExists = 1
    END
    ELSE
    BEGIN
        Print 'Table does not exists' 
        @TableExists = 0
    END

    RETURN @@TableExists = TableExists
Go

What I would like is the output either 1 or 0, so that I can check the result in C#

3
  • 1
    Why not just SELECT @TableExists = 1 FROM INFORMATION_SCHEMA.TABLES WHERE . . ? And remember to set the default value for @TableExists which is 0. Commented Jun 23, 2019 at 11:39
  • 1
    Don't use RETURN either for this; you should be using an OUTPUT parameter. Also, why would the table not exist here? I thought you might be checking for a table based on it's name, but you're not; so why wouldn't it exist at one point and then not later? If you need to it to be part of your design create it at the start; even if that table is empty. Commented Jun 23, 2019 at 11:46
  • You are reinventing the wheel, use this instead: learn.microsoft.com/en-us/sql/t-sql/functions/… Commented Jun 23, 2019 at 12:16

2 Answers 2

2

You can check if a table exists in multiple ways -- for instance, using metadata table or by attempting to access it.

In either case, you will want to use dynamic SQL.

Also, I strongly recommend returning values from a stored procedure using OUTPUT parameters, not RETURN. If you want RETURN you probably want a stored function.

I like Sami's approach of passing in the names of the components you are looking for. Here is a version that should work:

CREATE PROCEDURE dbo.CheckTableCountyExists (
    @DatabaseName SysName,
    @SchemaName SysName,
    @TableName SysName,
    @TableExists BIT = 0 OUTPUT
) AS
BEGIN
    DECLARE @sql NVARCHAR(MAX);

    SET @sql = '
SELET @TableExists =
          (CASE WHEN EXISTS (SELECT 1
                             FROM @DatabaseName.INFORMATION_SCHEMA.TABLES t
                             WHERE t.TABLE_SCHEMA = @SchemaName AND
                                   t.TABLE_NAME = @TableName
                            )
                THEN 1 ELSE 0
           END)';

    SET @sql = REPLACE(@sql, '@DatabaseName', QUOTENAME(@DatabaseName));

    EXEC sp_executesql @sql,
                       N'@SchemaName sysname, @TableName sysname, @TableExists BIT',
                       @SchemaName=@SchemaName, @TableName=@TableName, @TableExists=@TableExists;
END;

Then you call it as:

DECLARE @isExists BIT = 0;

EXEC dbo.CheckTableExists N'BlackCorsetDatabase', 
                          N'dbo', 
                          N'County', 
                          @isExists OUTPUT;

SELECT @isExists;

The above will fail, though, if the database does not exist. You can fix this with a TRY/CATCH. A generic method is:

CREATE PROCEDURE dbo.CheckTableCountyExists (
    @DatabaseName SysName,
    @SchemaName SysName,
    @TableName SysName,
    @TableExists BIT = 0 OUTPUT
) AS
BEGIN
    DECLARE @sql NVARCHAR(MAX);

    SET @sql = '
SELET @TableExists =
          (CASE WHEN EXISTS (SELECT 1
                             FROM @DatabaseName.INFORMATION_SCHEMA.TABLES t
                             WHERE t.TABLE_SCHEMA = @SchemaName AND
                                   t.TABLE_NAME = @TableName
                            )
                THEN 1 ELSE 0
           END)';

    SET @sql = REPLACE(@sql, '@DatabaseName', QUOTENAME(@DatabaseName));
    BEGIN TRY
        EXEC sp_executesql @sql,
                       N'@SchemaName sysname, @TableName sysname, @TableExists BIT',

@SchemaName=@SchemaName, 
@TableName=@TableName, 
@TableExists=@TableExists;
     END TRY
     BEGIN CATCH
         -- on any error, assume table does not exist
         SET @TableExists = 0
     END CATCH;
END;

Note: You could be more specific about the error. However, it is hard to imagine a situation where the code works but you get an error in the dynamic SQL and want to return "1".

Here is a db<>fiddle.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Guys for the help.
0

There is no need to all this code, and also don't use RETURN to return a value, it's for checking if the SP success or fail.

Your SP can be like

CREATE PROCEDURE [dbo].[CheckTableCountyExists]
(
  @DatabaseName SysName,
  @SchemaName SysName,
  @TableName SysName,
  @TableExists BIT = 0 OUTPUT
)
AS
  SELECT @TableExists = 1
  FROM INFORMATION_SCHEMA.TABLES
  WHERE TABLE_CATALOG = @DatabaseName
        AND
        TABLE_SCHEMA = @SchemaName
        AND
        TABLE_NAME = @TableName;
Go

Then you can use it as

DECLARE @MyVar BIT = 0;

EXEC [dbo].[CheckTableCountyExists] N'MyDatabaseName, 
                                    N'MySchemaName', 
                                    N'MyTableName', 
                                    @MyVar;

SELECT @MyVar;

In you can check the output variable @TableExists if it returns 0 (not exists) or 1 (exists).

1 Comment

@DatabaseName won't work as you expect here. Without dynamic SQL, the query will be run in the context of the database the SP exists in. Therefore you would always get a value of 0 if you try to check the existence of a table in a different database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.