sql 可以 运行 但是当你 运行 python 使用 sqlalchemy 编码时你失败了

sql is ok to run but when you run python code with sqlalchemy you failed

系统信息

mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 8.0.20    |
+-----------+
python -V
Python 2.7.12

sql 可以 运行

我用下面的sql,sql炼金输出,可以生成table.

CREATE TABLE images (
    created_at DATETIME,
    updated_at DATETIME,
    deleted_at DATETIME,
    deleted INTEGER,
    platform_id VARCHAR(36) NOT NULL,
    image_id VARCHAR(36) NOT NULL,
    PRIMARY KEY (platform_id, image_id)
);


CREATE TABLE flavors (
    created_at DATETIME,
    updated_at DATETIME,
    deleted_at DATETIME,
    deleted INTEGER,
    platform_id VARCHAR(36) NOT NULL,
    flavor_id VARCHAR(36) NOT NULL,
    PRIMARY KEY (platform_id, flavor_id)
);


CREATE TABLE security_groups (
    created_at DATETIME,
    updated_at DATETIME,
    deleted_at DATETIME,
    deleted INTEGER,
    platform_id VARCHAR(36) NOT NULL,
    name VARCHAR(255) NOT NULL,
    tenant_id VARCHAR(36),
    user_id VARCHAR(36),
    PRIMARY KEY (platform_id, name)
);


CREATE TABLE instances (
    created_at DATETIME,
    updated_at DATETIME,
    deleted_at DATETIME,
    deleted INTEGER,
    flavor_id VARCHAR(36),
    image_id VARCHAR(36),
    security_group_name VARCHAR(255),
    platform_id VARCHAR(36) NOT NULL,
    uuid VARCHAR(36) NOT NULL,
    user_id VARCHAR(36),
    tenant_id VARCHAR(36),
    `accessIPv4` VARCHAR(255),
    `accessIPv6` VARCHAR(255),
    progress INTEGER,
    config_drive BOOL,
    status VARCHAR(255),
    `hostId` VARCHAR(255),
    key_name VARCHAR(255),
    name VARCHAR(255),
    updated DATETIME,
    created DATETIME,
    launched_at DATETIME,
    terminated_at DATETIME,
    task_state VARCHAR(255),
    vm_state VARCHAR(255),
    instance_name VARCHAR(255),
    `diskConfig` VARCHAR(255),
    power_state INTEGER,
    availability_zone VARCHAR(255),
    host VARCHAR(255),
    hypervisor_hostname VARCHAR(255),
    PRIMARY KEY (platform_id, uuid),
    CHECK (config_drive IN (0, 1))
);

ALTER TABLE instances ADD CONSTRAINT flavor_instances_fk FOREIGN KEY(platform_id, flavor_id) REFERENCES flavors (platform_id, flavor_id)

但是当我使用我的迁移脚本时它失败并显示以下错误消息

发生错误:

回溯(最后一次调用): 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1277 行,在 _execute_context 游标、语句、参数、上下文 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/default.py”,第 593 行,在 do_execute 中 cursor.execute(声明,参数) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/cursors.py”,第 163 行,在执行中 结果 = self._query(查询) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/cursors.py”,第 321 行,在 _query 中 conn.query(q) 查询中的文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 505 行 self._affected_rows = self._read_query_result(无缓冲=无缓冲) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 724 行,在 _read_query_result 中 result.read() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 1069 行,已读 first_packet = self.connection._read_packet() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 676 行,在 _read_packet 中 packet.raise_for_error() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/protocol.py”,第 223 行,在 raise_for_error 中 err.raise_mysql_exception(self._data) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/err.py”,第 107 行,在 raise_mysql_exception 中 提高错误类(errno,errval) pymysql.err.OperationalError: (3780, “引用列 'platform_id' 和外键约束 'flavor_instances_fk' 中引用的列 'platform_id' 不兼容。”)

上述异常是以下异常的直接原因:

回溯(最后一次调用): 文件“/root/work/cpmsv2/cpmsv2/tests/functional/db/test_migrate.py”,第 118 行,位于 名称='flavor_instances_fk').create() 创建文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/constraint.py”,第 44 行 self.__do_imports('constraintgenerator', *a, **kw) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/constraint.py”,第 32 行,在 __do_imports 中 run_single_visitor(引擎, visitorcallable, self, *a, **kw) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/databases/visitor.py”,第 85 行,在 run_single_visitor 中 fn(元素, **kwargs) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/ansisql.py”,第 285 行,在 visit_migrate_foreign_key_constraint 中 self._visit_constraint(*p, **k) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/ansisql.py”,第 297 行,在 _visit_constraint 中 self.execute() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/migrate/changeset/ansisql.py”,第 44 行,在执行中 return self.connection.execute(self.buffer.getvalue()) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1003 行,在执行中 return self.execute_text(对象, 多参数, 参数) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1178 行,在 _execute_text 参数, 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1317 行,在 execute_context 中 e、语句、参数、游标、上下文 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1511 行,在 handle_dbapi_exception 中 sqlalchemy_exception, with_traceback=exc_info[2], 来自=e 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/util/compat.py”,第 182 行,在 raise 中 引发异常 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/base.py”,第 1277 行,在 _execute_context 游标、语句、参数、上下文 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/sqlalchemy/engine/default.py”,第 593 行,在 do_execute 中 cursor.execute(声明,参数) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/cursors.py”,第 163 行,在执行中 结果 = self._query(查询) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/cursors.py”,第 321 行,在 _query 中 conn.query(q) 查询中的文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 505 行 self._affected_rows = self._read_query_result(无缓冲=无缓冲) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 724 行,在 _read_query_result 中 result.read() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 1069 行,已读 first_packet = self.connection._read_packet() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py”,第 676 行,在 _read_packet 中 packet.raise_for_error() 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/protocol.py”,第 223 行,在 raise_for_error 中 err.raise_mysql_exception(self._data) 文件“/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/err.py”,第 107 行,在 raise_mysql_exception 中 提高错误类(errno,errval) sqlalchemy.exc.OperationalError:(pymysql.err.OperationalError)(3780,“外键约束 'flavor_instances_fk' 中引用列 'platform_id' 和引用列 'platform_id' 不兼容。”) [SQL: ALTER TABLE instances ADD CONSTRAINT flavor_instances_fk FOREIGN KEY(platform_id, flavor_id) REFERENCES flavors (platform_id, flavor_id )] (此错误的背景信息位于:http://sqlalche.me/e/13/e3q8) 详细信息 table 已在命名实例上方引用。 (此错误的背景信息位于:http://sqlalche.me/e/13/e3q8

可以重现错误的最小代码段如下所示

from sqlalchemy import create_engine
from sqlalchemy import Boolean, Column, DateTime, Enum, Float
from sqlalchemy import dialects
from sqlalchemy import ForeignKey, ForeignKeyConstraint, Index, Integer, MetaData, PrimaryKeyConstraint, String, Table # noqa
from sqlalchemy import Text

connection_string = 'your_connect_string'
engine = create_engine(connection_string, echo=True)
meta = MetaData()
meta.bind = engine
tables = []


instances = Table(
    'instances', meta,
    # Created by TimestampMixin
    Column('created_at', DateTime),
    Column('updated_at', DateTime),
    # Created by SoftDeleteMixin
    Column('deleted_at', DateTime),
    Column('deleted', Integer),

    Column('flavor_id', String(36)),
    Column('image_id', String(36)),
    Column('security_group_name', String(255)),

    Column('platform_id', String(36), primary_key=True),
    Column('uuid', String(36), primary_key=True),
    Column('user_id', String(36)),
    Column('tenant_id', String(36)),


    Column('accessIPv4', String(255)),
    Column('accessIPv6', String(255)),
    Column('progress', Integer),
    Column('config_drive', Boolean),
    Column('status', String(255)),
    Column('hostId', String(255)),
    Column('key_name', String(255)),
    Column('name', String(255)),

    Column('updated', DateTime),
    Column('created', DateTime),
    Column('launched_at', DateTime),
    Column('terminated_at', DateTime),

    Column('task_state', String(255)),
    Column('vm_state', String(255)),
    Column('instance_name', String(255)),
    Column('diskConfig', String(255)),
    Column('power_state', Integer),
    Column('availability_zone', String(255)),
    Column('host', String(255)),
    Column('hypervisor_hostname', String(255)),
    mysql_engine='InnoDB',
    mysql_charset='utf8'
)


images = Table(
    'images', meta,
    # Created by TimestampMixin
    Column('created_at', DateTime),
    Column('updated_at', DateTime),
    # Created by SoftDeleteMixin
    Column('deleted_at', DateTime),
    Column('deleted', Integer),

    Column('platform_id', String(36), primary_key=True),
    Column('image_id', String(36), primary_key=True),
)


flavors = Table(
    'flavors', meta,
    # Created by TimestampMixin
    Column('created_at', DateTime),
    Column('updated_at', DateTime),
    # Created by SoftDeleteMixin
    Column('deleted_at', DateTime),
    Column('deleted', Integer),

    Column('platform_id', String(36), primary_key=True),
    Column('flavor_id', String(36), primary_key=True),
)


security_groups = Table(
    'security_groups', meta,
    # Created by TimestampMixin
    Column('created_at', DateTime),
    Column('updated_at', DateTime),
    # Created by SoftDeleteMixin
    Column('deleted_at', DateTime),
    Column('deleted', Integer),

    Column('platform_id', String(36), primary_key=True),
    Column('name', String(255), primary_key=True),

    Column('tenant_id', String(36)),
    Column('user_id', String(36)),
)


tables.append(images)
tables.append(flavors)
tables.append(security_groups)
tables.append(instances)

meta.create_all(tables=tables)
from migrate import ForeignKeyConstraint, UniqueConstraint

# UniqueConstraint(instances.c.platform_id, instances.c.flavor_id,
#                  name='platform_flavor_constraint').create()
ForeignKeyConstraint([instances.c.platform_id, instances.c.flavor_id],
                     [flavors.c.platform_id, flavors.c.flavor_id],
                     name='flavor_instances_fk').create()
ForeignKeyConstraint([instances.c.platform_id, instances.c.image_id],
                     [images.c.platform_id, images.c.image_id],
                     name='image_instances_fk').create()
ForeignKeyConstraint([instances.c.platform_id, instances.c.security_group_name], # noqa
                     [security_groups.c.platform_id, security_groups.c.name],
                     name='sec_groups_instances_fk').create() # noqa

朋友yiwei提醒,tableinstancesflavors两个数据库的charset和collect不一样

参考代码如下

    Column('hypervisor_hostname', String(255)),
    mysql_engine='InnoDB',
    mysql_charset='utf8'

和其他 table 没有以下代码段

    mysql_engine='InnoDB',
    mysql_charset='utf8'