简体   繁体   English

有条件地从 Python 在 SQL 中创建临时表

[英]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.在大量查询中,我试图在 SQL 中创建一个临时表(如果它尚不存在)。 Obviously, you could remove the 2nd CREATE TABLE statement.显然,您可以删除第二个CREATE TABLE语句。 However, the queries I'm building are dynamic and may, or may not, have the 1st CREATE TABLE statement present.但是,我正在构建的查询是动态的,可能存在也可能不存在第一个CREATE TABLE语句。

I can get the following sample/test query to work in Microsoft SQL Server Management Studio.我可以让以下示例/测试查询在 Microsoft SQL Server Management Studio 中工作。 It was created with help from this SO question/answer它是在此 SO 问题/答案的帮助下创建的

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:当我在同一个数据库中运行以下代码,但使用pandas.io.sql.read_sqlpypyodbc我得到了随附的回溯:

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 ?有人可以帮助我使用pandas.io.sql.read_sql使查询工作吗? I'm open to switching to another odbc package like pyodbc , turbodbc , etc.我愿意切换到另一个 odbc 包,如pyodbcturbodbc等。

======= 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.根据其中一条评论,我尝试更改IF语句中的逻辑,因为在使用 ODBC 时,它似乎被标记为 TRUE。 This version also works in MSSMS, but gives me the same error in Python.这个版本也适用于 MSSMS,但在 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.当您删除GO ,您必须将其编译,然后同一个临时表有两个CREATE TABLE语句,它们不会解析和编译。 EG this batch generates the same error: EG 这个批次产生同样的错误:

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.要修复,只需删除第二个CREATE TABLE ,因为无论如何它都是不必要的。 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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