首页 > 解决方案 > 如何强制 SQLAlchemy 将布尔类型从 PostgreSQL 转换为 SQL Server 中的位类型

问题描述

我正在尝试将几个表从一个数据库(“db1”,PostgreSQL)复制到另一个(“db2”,SQL Server)。不幸的是,由于 PostgreSQL 数据库中某些字段的 BOOLEAN 类型不被识别为 SQL Server 的有效类型,我面临一个问题。

这是我的代码示例:

db2_engine = "postgresql+psycopg2://" + str(db2_user) + ":" + str(db2_password) + "@" + str(db2_host) + ":" + str(db2_port) + "/" + str(db2_database)
db2 = sqlalchemy.create_engine(db2_engine)

lst_tablename_totr = ["contract",
                     "subscription",
                     "contractdelivery",
                     "businesspartner"
                     ]

for table_name in lst_tablename_totr:
    table = Table(table_name, metadata, autoload=True, autoload_with=db2)
    table.create(bind=db1)
    query = """
    SELECT
        *
    FROM """ + str(table_name) + """
    """
    df_hg = pd.read_sql(query, db2_engine)
    df_hg.to_sql(table_name, db1, schema='dbo', index=False, if_exists='append')

目前,问题位于table = Table(table_name, metadata, autoload=True, autoload_with=db_hgzl) table.create(bind=db1)代码部分。

这是错误消息:

ProgrammingError: (pyodbc.ProgrammingError) ('42000', '[42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Column, parameter or variable #8\xa0: data type BOOLEAN not found. (2715) (SQLExecDirectW)')

我找不到任何方法来强制 PostgreSQL Boolean 类型和 SQL Server Bit 类型之间的转换。

标签: pythonsql-serverpostgresqlsqlalchemy

解决方案


BOOLEAN您会看到 SQLAlchemy 的特定方言类型与其泛型类型之间的差异Boolean。对于现有的 PostgreSQL 表

CREATE TABLE IF NOT EXISTS public.so68683260
(
    id character varying(5) COLLATE pg_catalog."default" NOT NULL,
    bool_col boolean NOT NULL,
    CONSTRAINT so68683260_pkey PRIMARY KEY (id)
)

如果我们反映该表,则布尔列定义为BOOLEAN

tbl = sa.Table(table_name, sa.MetaData(), autoload_with=pg_engine)
print(type(tbl.columns["bool_col"].type))
# <class 'sqlalchemy.sql.sqltypes.BOOLEAN'>

然后如果我们尝试在 SQL Server 中创建表,我们最终会做相当于

tbl = sa.Table(
    table_name,
    sa.MetaData(),
    sa.Column("id", sa.VARCHAR(5), primary_key=True),
    sa.Column("bool_col", sa.BOOLEAN, nullable=False),
)

tbl.drop(ms_engine, checkfirst=True)
tbl.create(ms_engine)

并因您引用的错误而失败,因为呈现的 DDL 是

CREATE TABLE so68683260 (
    id VARCHAR(5) NOT NULL, 
    bool_col BOOLEAN NOT NULL, 
    PRIMARY KEY (id)
)

但是,如果我们使用泛型Boolean类型

tbl = sa.Table(
    table_name,
    sa.MetaData(),
    sa.Column("id", sa.VARCHAR(5), primary_key=True),
    sa.Column("bool_col", sa.Boolean, nullable=False),
)

tbl.drop(ms_engine, checkfirst=True)
tbl.create(ms_engine)

我们成功了,因为渲染的 DDL 是

CREATE TABLE so68683260 (
    id VARCHAR(5) NOT NULL, 
    bool_col BIT NOT NULL, 
    PRIMARY KEY (id)
)

并且BIT是 T-SQL 中有效的对应列类型。

如果您认为应该更改此行为,请随意打开SQLAlchemy 问题。

[还要注意,文本列是VARCHAR(5)因为该表使用我的 PostgreSQL 测试数据库 (UTF8) 的默认编码,但是在 SQL Server 中创建表将创建一个VARCHAR(非 Unicode)列而不是NVARCHAR(Unicode)列。]


推荐阅读