2012-01-15 89 views
2

这里有一个问题给你mysql + python的人在那里。为什么会通过python创建表失败,但在cli上成功?

为什么这个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 

当我运行的蟒蛇,我得到的错误是这样的:


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) 
+0

什么是“DELIMITER //”应该做的?它当然看起来不像有效的SQL。 – millimoose 2012-01-15 20:00:44

回答

2

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

更新

你有2个错别字为同一DELIMIETER ; - 我相信翻译找到的第一个刚过你所得到的错误:

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 
+0

我知道我使用'DELIMITER; '在这里,但你能告诉我它应该是什么吗?我来自postgresql的思维模式,这种在MySQL中执行PL的方式让我感到困惑。 – bitcycle 2012-01-15 20:09:43

+1

我的东西没有什么错,你的使用 - 这是你写在你的Python代码的方式是错误的 - 你写了'DELIMIETER'而不是'DELIMITER'(参见'I'和'T'之间的额外'E') – 2012-01-15 20:19:41

+0

我需要拼写检查我的代码 - DOH! :) – bitcycle 2012-01-15 20:22:30

2

只能查询传递到MySQL一次一个;客户端要确保查询文本只是一个有效的语句。

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

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

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

相关问题