SQL ALTER和DROP数据库如果已存在,带有PYODBC

问题描述 投票:1回答:1

作为SQL新手,我试图确保将数据最初导入数据库不会创建重复条目,并且将以编程方式创建数据库。如果有一种更有效的方法(执行告诉操作),我不会感到惊讶,但是我的方法是删除数据库并重新创建它(如果已经存在),据我所知这是非常快的。我已经在函数外部成功使用了同一条语句,并且没有格式化字符串,但是在创建函数来执行此操作时,我通过PYODBC收到错误:

ProgrammingError: ('42S22', "[42S22] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Invalid column name 'test'. (207) (SQLExecDirectW)")

这很令人困惑,因为我没有尝试引用任何列,更不用说表了;因此很难进行故障排除。功能如下:

def db_connect(db, driver='ODBC Driver 17 for SQL Server', host='', UID='', PWD='', autocommit=False):
    """Returns a connection and a cursor object for the specified database."""
    conn = pyodbc.connect(driver=driver,
                        host=host,
                        database=db,
                        UID=UID,
                        PWD=PWD,
                        autocommit=autocommit
                        )
    print(f'Connect established to database {db}')
    return conn, conn.cursor()

def db_clear(db, recreate=True):
    """Drops and recreates the specified database, ready for insert."""
    conn, curs = db_connect('master')
    curs.execute(f"""IF EXISTS (SELECT name from sys.databases WHERE (name = {db}))
        BEGIN
            ALTER DATABASE {db} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
            DROP DATABASE {db};
        END;""")
    if recreate:
        curs.execute(f"CREATE DATABASE {db};")
        conn.close()
        print(f'{db} successfully dropped and recreated.')
    else:
        print(f'{db} successfully dropped.')
    return

db_clear('test')

[包含END;""")的行上引发了异常。工作版本(函数中未包含)和此函数版本之间只有两个区别,即我开始使用较新的驱动程序来更好地处理数据类型转换,并且在这些功能完成后,我关闭了自动提交功能以批量插入他们的工作。我尝试将这两个选项都恢复为函数中的原始设置,但收到相同的错误。任何帮助表示赞赏!

python sql pyodbc
1个回答
0
投票

您的字符串格式

f"""IF EXISTS (SELECT name from sys.databases WHERE (name = {db}))
    BEGIN
        ALTER DATABASE {db} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
        DROP DATABASE {db};
    END;"""

正在生产

IF EXISTS (SELECT name from sys.databases WHERE (name = test))
BEGIN
    ALTER DATABASE test SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE test;
END;

并且当SQL解析器看到WHERE (name = test)时,它将test解释为列名(在sys.databases表/视图中),就像它(正确)将name解释为列名一样。

相反,您要做的是向WHERE子句提供parameter value

sql = f"""IF EXISTS (SELECT name from sys.databases WHERE (name = ?))
          BEGIN
              ALTER DATABASE [{db}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
              DROP DATABASE [{db}];
          END;"""
curs.execute(sql, db)
© www.soinside.com 2019 - 2024. All rights reserved.