You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SQLAlchemy从SQL Server迁移数据到MariaDB时遇类型错误

SQLAlchemy迁移SQL Server到MariaDB报错解决

问题背景

尝试用SQLAlchemy将SQL Server的customers表数据迁移到MariaDB,两张表结构基本一致:

MariaDB表结构

CREATE TABLE IF NOT EXISTS customers
(
    id           INT PRIMARY KEY,
    first_name   VARCHAR(50)  NOT NULL,
    last_name    VARCHAR(50)  NOT NULL,
    email        VARCHAR(50)  NOT NULL UNIQUE,
    phone_number VARCHAR(15)  NOT NULL,
    address      VARCHAR(150) NOT NULL,
    city         VARCHAR(50)  NOT NULL,
    state        VARCHAR(50)  NOT NULL,
    zip_code     VARCHAR(10)  NOT NULL,
    create_date  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_date  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

SQL Server表结构

CREATE TABLE customers
(
    id           INT PRIMARY KEY IDENTITY (1,1),
    first_name   VARCHAR(50)  NOT NULL,
    last_name    VARCHAR(50)  NOT NULL,
    email        VARCHAR(50)  NOT NULL UNIQUE,
    phone_number VARCHAR(15)  NOT NULL,
    address      VARCHAR(150) NOT NULL,
    city         VARCHAR(50)  NOT NULL,
    state        VARCHAR(50)  NOT NULL,
    zip_code     VARCHAR(10)  NOT NULL,
    create_date  DATETIME DEFAULT CURRENT_TIMESTAMP,
    update_date  DATETIME DEFAULT CURRENT_TIMESTAMP
);

迁移代码

def main():
    # Connection strings
    sql_server_conn_str = CONFIG['connectionStrings']['sqlServer']
    maria_conn_str = CONFIG['connectionStrings']['mariaDb']

    # create SQLAlchemy engine for SQL Server and MariaDB
    sql_server_engine = create_engine(sql_server_conn_str)
    maria_engine = create_engine(maria_conn_str)

    # create connection for both db
    sql_server_conn = sql_server_engine.connect()
    maria_conn = maria_engine.connect();

    # create SQLAlchemy MetaData objects for SQL Server and MariaDB
    sql_server_metadata = MetaData()
    maria_metadata = MetaData()

    # reflect the SQL Server database schema into the MetaData object
    sql_server_metadata.reflect(bind=sql_server_engine)

    # create Table objects for each SQL Server table
    customers_sql_server = Table('customers', sql_server_metadata, autoload=True, autoload_with=sql_server_engine)

    # reflect the MariaDB database schema into the MetaData object
    maria_metadata.reflect(bind=maria_engine)

    # create Table objects for each MariaDB table
    customers_maria = Table('customers', maria_metadata, autoload=True, autoload_with=maria_engine)

    # select all rows from the customers table in SQL Server
    select_customers_sql_server = select(customers_sql_server)

    # execute the select query and fetch all rows
    result_proxy = sql_server_conn.execute(select_customers_sql_server)
    customers_data = result_proxy.fetchall()

    # insert the rows into the customers table in MariaDB
    tuples_to_insert = [tuple(row) for row in customers_data]
    maria_conn.execute(customers_maria.insert(), tuples_to_insert)

报错信息

Traceback (most recent call last):   ...\main.py", line 48, in <module>
        main()   File "...\main.py", line 35, in main
        maria_conn.execute(customers_maria.insert(), tuples_to_insert)   File "...\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1413, in execute
        return meth(
               ^^^^^   File "...\venv\Lib\site-packages\sqlalchemy\sql\elements.py", line 483, in
    _execute_on_connection
        return connection._execute_clauseelement(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   File "...\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1613, in
    _execute_clauseelement
        keys = sorted(distilled_parameters[0])
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

TypeError: '<' not supported between instances of 'str' and 'int'

错误原因

报错是因为SQLAlchemy处理批量插入时,同时收到了两种参数格式:从SQL Server取出的元组是位置参数,但insert()方法默认期望批量插入的是字典列表(关键字参数)。内部处理时,参数键同时存在字符串(列名)和数字(索引)类型,排序时触发类型不兼容的错误。


解决方法

把从SQL Server取出的行数据转换成字典(键对应列名),让SQLAlchemy能准确匹配MariaDB表的字段,避免参数类型混乱。

修改后的代码

def main():
    # Connection strings
    sql_server_conn_str = CONFIG['connectionStrings']['sqlServer']
    maria_conn_str = CONFIG['connectionStrings']['mariaDb']

    # create SQLAlchemy engine for SQL Server and MariaDB
    sql_server_engine = create_engine(sql_server_conn_str)
    maria_engine = create_engine(maria_conn_str)

    # create connection for both db
    sql_server_conn = sql_server_engine.connect()
    maria_conn = maria_engine.connect()

    # create SQLAlchemy MetaData objects for SQL Server and MariaDB
    sql_server_metadata = MetaData()
    maria_metadata = MetaData()

    # reflect the SQL Server database schema into the MetaData object
    sql_server_metadata.reflect(bind=sql_server_engine)

    # create Table objects for each SQL Server table
    customers_sql_server = Table('customers', sql_server_metadata, autoload=True, autoload_with=sql_server_engine)

    # reflect the MariaDB database schema into the MetaData object
    maria_metadata.reflect(bind=maria_engine)

    # create Table objects for each MariaDB table
    customers_maria = Table('customers', maria_metadata, autoload=True, autoload_with=maria_engine)

    # select all rows from the customers table in SQL Server
    select_customers_sql_server = select(customers_sql_server)

    # execute the select query and fetch all rows, convert to dictionaries
    result_proxy = sql_server_conn.execute(select_customers_sql_server)
    # 将行数据转为字典,键为列名
    customers_data = [dict(row) for row in result_proxy]

    # insert the rows into the customers table in MariaDB
    maria_conn.execute(customers_maria.insert(), customers_data)
    # 提交事务,确保数据持久化
    maria_conn.commit()

补充说明

  1. 替换tuple(row)为dict(row):字典格式能明确匹配字段,即使后续表结构调整(如列顺序变化)也不会出错,比元组更健壮。
  2. 添加maria_conn.commit():部分SQLAlchemy引擎默认不自动提交事务,必须手动提交才能完成数据插入。
  3. 若确认两张表列顺序完全一致,也可使用maria_conn.execute(customers_maria.insert().values(tuples_to_insert))插入元组列表,但字典方式更推荐。

内容的提问来源于stack exchange,提问作者Oleg Ivsv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 23:27:43