从Django调用Postgres SQL存储过程

6

我正在处理一个使用Postgres SQL数据库的Django项目。我已经编写了一个在Postgres上完美运行的存储过程。

现在我想从Django 1.5调用该存储过程..我已经编写了代码,但它引发了错误。

CREATE FUNCTION fn_save_message3(IN msg_sub character varying, IN msg_cont text, IN msg_type character varying, IN msg_category character varying, IN msg_created_by character varying, IN msg_updated_by character varying) RETURNS integer AS
$BODY$ DECLARE msg_id integer := 0;
BEGIN
    INSERT INTO tbl_messages
        (message_subject, message_content, message_type, message_category, 
       created_on, created_by, updated_on, updated_by)
    VALUES 
      (msg_sub, msg_cont, msg_type, msg_category, LOCALTIMESTAMP, 
       msg_created_by, LOCALTIMESTAMP, msg_updated_by);
      Select into msg_id currval('tbl_messages_message_id_seq');
  return msg_id;
END;$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF
COST 100;
ALTER FUNCTION public.fn_save_message(IN character varying, IN text, IN character varying, IN character varying, IN character varying, IN character varying)
  OWNER TO gljsxdlvpgfvui;

存储过程正常并返回结果。
c = connection.cursor()
    try:
        c.execute("BEGIN")
        c.callproc("fn_save_message", [Message_Subject, Message_Content, Message_Type, Message_Category, Created_By, updated_by])
        results = c.fetchone()
        c.execute("COMMIT")
    finally:
        c.close()
    print results

在你的建议下,我的程序终于能够正常工作了。但还有一个小问题。
我使用results = c.fetchone()来获取输出参数。 它返回(13,) 但我只想要将13作为字符串或整数获取,怎样才能只获取值。 更新: 问题已经解决。
for item in results:
        message_id = item

缩进问题?我并不认为这与SQL方面有任何关系。另外,请使用放置参数而不是字符串连接;请参见http://bobby-tables.com/,http://en.wikipedia.org/wiki/SQL_injection,http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries - Craig Ringer
为什么不在Django ORM中运行该代码? - Bobort
3个回答

6
c = connection.cursor()
try:
    c.execute("BEGIN")
    c.callproc("fn_save_message3", (Message_Subject, Message_Content, Message_Type, Message_Category, Created_By, Updated_By))
    results = c.fetchall()
    c.execute("COMMIT")
finally:
    c.close()
print results

你忘记了闭括号,试图在cursor上调用函数而不是c,并且出现了缩进问题。你还应该使用这里记录的callproc()函数。正如catavaran所说,你应该阅读关于执行自定义SQL和使用占位符的文档。此外,在Django 1.6+中,事务会自动提交,因此不需要执行"c.execute("COMMIT")"。

正如您所说,我已经更新了我的代码,现在出现了不同的错误,请查看我现在更新的问题。它应该接受输入参数,因为我没有定义它只能接受最多2个参数。 - Muhammad Taqi
1
@MuhammadTaqiHassanBukhari 更新了答案。新的错误意味着callproc()方法期望2个参数而不是7个。http://initd.org/psycopg/docs/cursor.html#cursor.callproc - Michał Czapliński

1
    c = connection.cursor()
    try:
        c.execute("BEGIN")
        c.callproc("fn_save_message3", [Message_Subject, Message_Content, Message_Type, Message_Category, Created_By, updated_by])
        results = c.fetchone()
        c.execute("COMMIT")
    finally:
        c.close()
    for item in results:
        message_id = item

0

c.execute("SELECT fn_save_message3(...行缺少了一个右括号。请在最后一个引号符号之后添加)

但无论如何,这是一种错误的方法来执行Python代码中的SQL。您应该使用占位符来防止SQL注入攻击。阅读文档以了解在Django中正确使用SQL的示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接