简体   繁体   中英

Conditionally Create Temp Table in SQL from Python

In a large set of queries, I'm trying to create a temp table in SQL, if it doesn't already exist. Obviously, you could remove the 2nd CREATE TABLE statement. However, the queries I'm building are dynamic and may, or may not, have the 1st CREATE TABLE statement present.

I can get the following sample/test query to work in Microsoft SQL Server Management Studio. It was created with help from this SO question/answer

SET NOCOUNT ON;

DROP TABLE IF EXISTS #temp_sample;
CREATE TABLE #temp_sample (
    id VARCHAR(15) NOT NULL,
    datetime DATETIME,
    location VARCHAR(255)
);
GO 
    
INSERT INTO #temp_sample (id, datetime, location)
VALUES ('ABC', '2021-06-04 15:52:44', 'PENNSYLVANIA'),('123', '2021-06-04 15:52:49', 'PENNSYLVANIA');

IF (OBJECT_ID('tempdb..#temp_sample') IS NULL)
    BEGIN
        CREATE TABLE #temp_sample (
            id VARCHAR(15) NOT NULL,
            datetime DATETIME,
            location VARCHAR(255)
        );
    END
ELSE 
    PRINT '#temp_sample already exists... skipping'
GO

SELECT * FROM #temp_sample

WHEN I run the following code in the same database, but using pandas.io.sql.read_sql and pypyodbc I get the accompanying traceback:

import pypyodbc
import pandas.io.sql as psql

connection_string = 'DSN=dsn_name;UID=username;PWD=password;app=app_name;'
cnxn = pypyodbc.connect(connection_string)
temp_db_query = '''
    SET NOCOUNT ON;
       
    DROP TABLE IF EXISTS #temp_sample;
    CREATE TABLE #temp_sample (
        id VARCHAR(15) NOT NULL,
        datetime DATETIME,
        location VARCHAR(255)
    );
    GO

    INSERT INTO #temp_sample (id, datetime, location)
    VALUES ('ABC', '2021-06-04 15:52:44', 'PENNSYLVANIA'),('123', '2021-06-04 15:52:49', 'PENNSYLVANIA');

    IF (OBJECT_ID('tempdb..#temp_sample') IS NULL)
        BEGIN
            CREATE TABLE #temp_sample (
                id VARCHAR(15) NOT NULL,
                datetime DATETIME,
                location VARCHAR(255)
            );
        END
    ELSE
        PRINT '#temp_sample already exists... skipping'
    GO

    SELECT * FROM #temp_sample
'''

df = psql.read_sql(temp_db_query, cnxn)
cnxn.close()
Traceback (most recent call last):
    File "/Users/user/miniconda3/envs/myenv/lib/python3.6/site-packages/pandas/io/sql.py", line 1595, in execute 
        cur.execute(*args)
    File "/Users/user/miniconda3/envs/myenv/lib/python3.6/site-packages/pypyodbc.py", line 1626, in execute 
        self.execdirect(query_string)
    File "/Users/user/miniconda3/envs/myenv/lib/python3.6/site-packages/pypyodbc.py", line 1652, in execdirect 
        check_success(self, ret)
    File "/Users/user/miniconda3/envs/myenv/lib/python3.6/site-packages/pypyodbc.py", line 1007, in check_success
        ctrl_err(SQL_HANDLE_STMT, ODBC_obj.stmt_h, ret, ODBC_obj.ansi)
    File "/Users/user/miniconda3/envs/myenv/lib/python3.6/site-packages/pypyodbc.py", line 975, in ctrl_err
        raise ProgrammingError(state,err_text)
pypyodbc.ProgrammingError: ('42S01', "[42S01] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]There is already an object named '#temp_sample' in the database.")

Can someone help me get the query to work using pandas.io.sql.read_sql ? I'm open to switching to another odbc package like pyodbc , turbodbc , etc.

======= UPDATE ========

Based on one of the comments, I tried changing the logic in the IF statement because it appears that, when using ODBC, it's getting flagged as TRUE. This version also works in MSSMS, but gives me the same error in Python. Is there another version that works?

    IF EXISTS (SELECT * FROM tempdb.sys.tables WHERE name LIKE '#temp_sample%')
        PRINT '#temp_sample already exists... skipping'
    ELSE
        BEGIN
            CREATE TABLE #temp_sample (
                id VARCHAR(15) NOT NULL,
                datetime DATETIME,
                location VARCHAR(255)
            );
        END
    GO

This is a batch compilation error. When you remove the GO , which you must to to get this to compile, then there are two CREATE TABLE statements for the same temp table, which won't parse and compile. EG this batch generates the same error:

CREATE TABLE #temp_sample (id int)
if 1=0
begin
  CREATE TABLE #temp_sample (id int)
end

To fix, just remove the second CREATE TABLE , as it's unnecessary anyway. EG

SET NOCOUNT ON;
   
DROP TABLE IF EXISTS #temp_sample;
CREATE TABLE #temp_sample (
    id VARCHAR(15) NOT NULL,
    datetime DATETIME,
    location VARCHAR(255)
);

INSERT INTO #temp_sample (id, datetime, location)
VALUES ('ABC', '2021-06-04 15:52:44', 'PENNSYLVANIA'),('123', '2021-06-04 15:52:49', 'PENNSYLVANIA');

SELECT * FROM #temp_sample

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM