提问者:小点点

sql可以运行,但使用sqlalchemy运行python代码时失败了


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

我使用下面sqlalchemy输出的sql,创建表是可以的。

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)

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

出现错误:

Traceback(最近一次调用最后):File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/Engine/base.py",第1277行,_execute_context游标,语句,参数,上下文File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/Engine/default.py",第593行,在do_executecursor.execute(语句,参数)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/cursors.py",第163行,在执行结果=自我。_query(查询)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/cursors.py",第321行,在_queryconn.query(q)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/connections.py",第505行,在查询自我中。_affected_rows=自我。_read_query_result(unbu据称)File"/root/。Virtualenvs/cpmsv2/lib/python3.7/site-包/pymysql/connections.py",第724行,_read_query_resultresult.read()File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/connections.py",第1069行,first_packet=self.connection._read_packet()File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/connections.py",第676行,_read_packetpacket.raise_for_error()File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/protocol.py",第223行,在raise_for_errorerr.raise_mysql_exception(自己。_data)File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-pack/pymysql/err.py",第107行,在raise_mysql_exception中提高错误类(errno,errval)pymysql.err.操作错误:(3780,引用列'platform_id'和引用外键约束flavor_instances_fk中的列platform_id不兼容。")

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

Traceback(最近调用最后一次):File"/root/work/cpmsv2/cpmsv2/test/功能/db/test_migrate.py",第118行,名称为='flavor_instances_fk')。在创建自。__do_imports(“约束生成器”,*a,**kw)文件“/root/. Virtualenvs/cpmsv2/lib/python3.7/site-pack/迁移/变更集/constraint.py”,第32行,__do_importsrun_single_visitor(引擎,visitorcall,自,*a,**kw)文件”/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/迁移/变更集/数据库/visitor.py",第85行,run_single_visitorfn(元素,**kwargs)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/迁移/变更集/ansisql.py",第285行,visit_migrate_foreign_key_constraint。_visit_constraint(*p,**k)文件"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-pack/迁移/变更集/ansisql.py",第297行,_visit_constraintself.execute()文件"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-Packes/迁移/变更集/ansisql.py",第44行,正在执行返回self.connection.execute(self.buffer.getvalue())File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-pack/sqlalChemy/Engine/base.py",第1003行,在执行返回self.execute_text(对象,多参数,参数)File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/引擎/base.py",第1178行,_execute_text参数,File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/引擎/base.py",第1317行,execute_contexte,语句,参数,光标,上下文File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/引擎/base.py",第1511行,handle_dbapi_exceptionsqlalchemy_exception,with_traceback=exc_info[2],from=e File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/util/compat.py",第182行,在提升提升中异常文件"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/引擎/base.py",第1277行,_execute_context光标、语句、参数、上下文文件"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/sqlalChemy/引擎/default.py",第593行,在do_executecursor.execute(语句,参数)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/cursors.py",第163行,在执行结果=自己。_query(查询)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/cursors. py",第321行,在_queryconn. Query(q)File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/pymysql/连接. py"中,第505行,在查询自.中。_affected_rows=自._read_query_result(unbu0007=unbu0007)File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/pymysql/连接. py",第724行,在_read_query_result结果. read()File"中/root/.virtualenvs/cpmsv2/lib/python3.7/site-packages/pymysql/connections.py",第1069行,在_read_packet数据包中读取first_packet=自己。连接。_read_packet()File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/pymysql/连接. py",第676行。raise_for_error()File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-包/pymysql/_data)File"/root/. Virtualenvs/cpmsv2/lib/python3.7/site-pack/pymysql/err. py",第223行,在raise_for_errorerr.raise_mysql_exception(自己的.constraint.py)File"/root/. viralenvs/cpmsv2/lib/python3.7/site-包/pymysql/err. py",第107行,在raise_mysql_exception提高errorclass(errno,errval)sqlalchey. exc。操作错误:(pymysql. err.(3780,"引用列'platform_id'和外键约束'flavor_instances_fk'中引用列'platform_id'不兼容。")[SQL: ALTER TABLE实例ADD CONSTRAINTflavor_instances_fkFOREIGN KEY(platform_id,flavor_id)REFERENCES口味(platform_id,flavor_id)](此错误的背景:超文本协议://sqlalche. me/e/13/e3q8)上面引用了详细信息表。(有关此错误的背景信息:超文本传输协议://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

共1个答案

匿名用户

由我的朋友yiwei提醒,两个表实例风格的数据库的字符集和集合是不同的。

参考代码如下

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

和其他表没有以下代码段

    mysql_engine='InnoDB',
    mysql_charset='utf8'