【问题标题】:Why would create table fail via python but succeed on cli?为什么创建表会通过 python 失败但在 cli 上成功?
【发布时间】:2012-02-10 23:19:13
【问题描述】:

这里有一个 mysql + python 人的问题。

为什么这个mysql sql命令序列在我通过Python执行时不起作用,但在我通过mysql CLI执行时却起作用?


#!/usr/bin/env python

import oursql as mysql
import sys, traceback as tb
import logging

# some other stuff...

class MySqlAuth(object):
    def __init__(self, host = None, db = None, user = None, pw = None, port = None):
        self.host = 'localhost' if host is None else host
        self.db = 'mysql' if db is None else db
        self.user = 'root' if user is None else user
        self.pw = pw
        self.port = 3306 if port is None else port

    @property
    def cursor(self):
        auth_dict = dict()
        auth_dict['host'] = self.host
        auth_dict['user'] = self.user
        auth_dict['passwd'] = self.pw
        auth_dict['db'] = self.db
        auth_dict['port'] = self.port
        conn = mysql.connect(**auth_dict)
        cur = conn.cursor(mysql.DictCursor)
        return cur

def ExecuteNonQuery(auth, sql):
    try:
        cur = auth.cursor
        log.debug('SQL:  ' + sql)
        cur.execute(sql)
        cur.connection.commit()
        return cur.rowcount
    except:
        cur.connection.rollback()
        log.error("".join(tb.format_exception(*sys.exc_info())))
    finally:
        cur.connection.close()

def CreateTable(auth, table_name):

    CREATE_TABLE = """
    CREATE TABLE IF NOT EXISTS %(table)s ( 
              uid VARCHAR(120) PRIMARY KEY
            , k VARCHAR(1000) NOT NULL
            , v BLOB
            , create_ts TIMESTAMP NOT NULL
            , mod_ts TIMESTAMP NOT NULL
            , UNIQUE(k)
            , INDEX USING BTREE(k)
            , INDEX USING BTREE(mod_ts) );
    """
    ExecuteNonQuery(auth, CREATE_TABLE % { 'table' : table_name })

    CREATE_BEFORE_INSERT_TRIGGER = """
    DELIMITER //
    CREATE TRIGGER %(table)s_before_insert BEFORE INSERT ON %(table)s
    FOR EACH ROW
    BEGIN
        SET NEW.create_ts = NOW();
        SET NEW.mod_ts = NOW();
        SET NEW.uid = UUID();
    END;// DELIMIETER ;
    """
    ExecuteNonQuery(auth, CREATE_BEFORE_INSERT_TRIGGER % { 'table' : table_name })

    CREATE_BEFORE_INSERT_TRIGGER = """
    DELIMITER //
    CREATE TRIGGER %(table)s_before_update BEFORE UPDATE ON %(table)s
    FOR EACH ROW
    BEGIN
        SET NEW.mod_ts = NOW();
    END;// DELIMIETER ;
    """
    ExecuteNonQuery(auth, CREATE_BEFORE_UPDATE_TRIGGER % { 'table' : table_name })

# some other stuff

我在运行 python 时遇到的错误是这样的:


2012-01-15 11:53:00,138 [4214 MainThread mynosql.py] DEBUG SQL:  
    DELIMITER //
    CREATE TRIGGER nosql_before_insert BEFORE INSERT ON nosql
    FOR EACH ROW
    BEGIN
        SET NEW.create_ts = NOW();
        SET NEW.mod_ts = NOW();
        SET NEW.uid = UUID();
    END;// DELIMIETER ;

2012-01-15 11:53:00,140 [4214 MainThread mynosql.py] ERROR Traceback (most recent call last):
  File "./mynosql.py", line 39, in ExecuteNonQuery
    cur.execute(sql)
  File "cursor.pyx", line 120, in oursql.Cursor.execute (oursqlx/oursql.c:15856)
  File "cursor.pyx", line 111, in oursql.execute (oursqlx/oursql.c:15728)
  File "statement.pyx", line 157, in oursql._Statement.prepare (oursqlx/oursql.c:7750)
  File "statement.pyx", line 127, in oursql._Statement._raise_error (oursqlx/oursql.c:7360)
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER //\n    CREATE TRIGGER nosql_before_insert BEFORE INSERT ON nosql\n    F' at line 1", None)

【问题讨论】:

  • “DELIMITER //”应该做什么?它肯定看起来不像是有效的 SQL。

标签: python mysql create-table


【解决方案1】:

虽然你得到的错误似乎是由第一个 DELIMITER // 语句产生的,但你在最后一次提到 DELIMITER 时有一个错字 - 你写了它 DELIMIETER ; - 尝试改变它,看看是否能解决你的问题。

更新

对于同一个DELIMIETER ;,您有 2 个拼写错误 - 我相信您在解释器找到第一个错误之后就会收到错误:

 DELIMITER //
    CREATE TRIGGER %(table)s_before_insert BEFORE INSERT ON %(table)s
    FOR EACH ROW
    BEGIN
        SET NEW.create_ts = NOW();
        SET NEW.mod_ts = NOW();
        SET NEW.uid = UUID();
    END;// DELIMIETER ; <-- this one is wrong, it should be DELIMITER

【讨论】:

  • 我知道我在这里使用DELIMITER ; 有问题,但你能告诉我它应该是什么吗?我来自 postgresql 思维模式,这种在 mysql 中进行 PL 的方式让我感到困惑。
  • 我认为您的使用没有任何问题-这是您在python代码中编写它的方式错误-您编写了DELIMIETER而不是DELIMITER(请参阅@之间的额外E 987654330@和T)
【解决方案2】:

您一次只能向 mysql 传递一个查询;由客户来确保查询文本只是一个有效的语句。

MySQL 客户端通过标记输入的查询并查找语句分隔符来完成此操作。在触发器定义的情况下,这不起作用,因为定义可以包含分号(默认语句分隔符),因此您必须使用DELIMITER 命令告诉 cli 以另一种方式分隔语句。

MySQLdb(和其他)python api 不需要这样的语句分隔;程序员有义务一次将语句传递给query

尝试从查询中完全删除 DELIMITER 语句(通过 python api 传递时)。

【讨论】:

    猜你喜欢
    • 2010-12-13
    • 2018-07-07
    • 1970-01-01
    • 2010-09-20
    • 2020-11-07
    • 2021-07-05
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多