python-3.x Pandas df.to_sql()需要管理员权限才能追加,使用管理员权限进行追加将替换标题

lzfw57am  于 2023-07-01  发布在  Python
关注(0)|答案(2)|浏览(145)

我有一个SQL Server数据库,里面有几个表。所有的表都已经创建好了,带有自动递增的键和我需要的所有列。
现在我想从一个dataframe向一个表中写入额外的行。

def write_to_database(self, s_table, df):
    s_host = 'localhost'
    s_driver = 'SQL Server'
    port = 1433
    s_database = 'test'
    d_users = {
        'admin': ('censored', 'censored'),
        'user': ('censored', 'censored'),
    }
    s_username, s_pw = d_users.get('user', ('empty', 'empty'))
    mysql_engine = create_engine(
        f"mssql+pyodbc://{s_username}:{s_pw}@{s_host}:{port}/{s_database}?driver={s_driver}",
        pool_reset_on_return=None,  # disable default reset-on-return scheme
        use_setinputsizes=False
    )
        
    con = mysql_engine.connect()
    df.to_sql(name=f'type__{s_table}', con=con, if_exists='append', index=False)

但我得到了这个例外:
pyodbc.ProgrammingError:('42000',“[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]CREATE TABLE权限在数据库'{test'中被拒绝。(262)(SQLExecDirectW)”)
我不想创建新表。我想添加到现有的一个!
当我使用管理员凭据时,现有的表将被替换为新表。
新表包含所有标题(除了index),但都是text类型,并且自动递增的唯一键不再可用

jhiyze9q

jhiyze9q1#

1.使用“用户”凭据时出现权限错误:错误消息表明指定的用户帐户没有在“test”数据库中创建新表所需的权限。若要解决此问题,应授予“user”帐户将数据插入现有表所需的权限。可以使用SQL Server Management Studio或通过执行适当的SQL命令将目标表的INSERT权限授予“user”帐户来执行此操作。
1.使用“admin”凭据时替换现有表:默认情况下,如果指定的表不存在,Pandas中的to_sql方法会创建一个新表。如果要将数据追加到现有表中,则应将to_sql函数调用中的if_exists参数修改为'append'。此外,可以使用dtype参数指定目标表中的列数据类型,以确保它们与原始表结构匹配。

from sqlalchemy import create_engine

def write_to_database(self, s_table, df):
    s_host = 'localhost'
    s_driver = 'SQL Server'
    port = 1433
    s_database = 'test'
    d_users = {
        'admin': ('censored', 'censored'),
        'user': ('censored', 'censored'),
    }
    s_username, s_pw = d_users.get('user', ('empty', 'empty'))
    mysql_engine = create_engine(
        f"mssql+pyodbc://{s_username}:{s_pw}@{s_host}:{port}/{s_database}?driver={s_driver}",
        pool_reset_on_return=None,  # disable default reset-on-return scheme
        use_setinputsizes=False
    )
    
    with mysql_engine.connect() as con:
        # Get the column data types from the existing table
        table_info = con.execute(f"SELECT TOP 1 * FROM {s_table}")
        column_types = {column[0]: column[1] for column in table_info.cursor_description}
        
        # Append data to the existing table
        df.to_sql(name=s_table, con=con, if_exists='append', index=False, dtype=column_types)

确保将s_table替换为目标表的实际名称。代码从现有表中检索列数据类型,并在编写DataFrame时使用它们以确保兼容性。

46scxncf

46scxncf2#

from sqlalchemy import create_engine, inspect

def write_to_database(self, s_table, df):
    s_host = 'localhost'
    s_driver = 'SQL Server'
    port = 1433
    s_database = 'test'
    d_users = {
        'admin': ('censored', 'censored'),
        'user': ('censored', 'censored'),
    }
    s_username, s_pw = d_users.get('user', ('empty', 'empty'))
    mysql_engine = create_engine(
        f"mssql+pyodbc://{s_username}:{s_pw}@{s_host}:{port}/{s_database}?driver={s_driver}",
        pool_reset_on_return=None,  # disable default reset-on-return scheme
        use_setinputsizes=False
    )
    
    with mysql_engine.connect() as con:
        inspector = inspect(con)
        
        if s_table not in inspector.get_table_names():
            raise ValueError(f"The table '{s_table}' does not exist in the database.")
        
        # Get the column information from the existing table
        columns = inspector.get_columns(s_table)
        column_names = [column['name'] for column in columns]
        
        # Filter DataFrame columns to match the existing table structure
        df = df[column_names]
        
        # Generate the INSERT INTO statement and append the data to the existing table
        insert_statement = f"INSERT INTO {s_table} ({', '.join(column_names)}) VALUES (?, ?, ?)"
        data = [tuple(row) for row in df.values.tolist()]
        con.execute(insert_statement, data)

相关问题