如何在 DO 语句中使用准备好的语句?

How to use prepared statements in DO statements?

我有一个相当复杂的查询,我试图使用准备好的语句来保护我的数据库免受 SQL 注入。我基本上将多个查询链接在一个 begin-end 块下。

此复合查询首先检查用户会话是否存在,然后检查用户是否已被禁止,然后检查用户输入的标签是否有效,最后将 post 插入数据库。

这里是查询:

query = "DO
    $$
    BEGIN
        IF 
            (select exists(select user_id from sessions where unqid =  and user_id = ))
        THEN
            IF 
                (select banned_till from users where unqid = ) > now() 
            THEN
                RAISE EXCEPTION 'User has been banned!';
            ELSE 
                IF (
                    Select ( SELECT array_agg(DISTINCT name) FROM allowed_tags) @> ) 
                THEN
                    insert into posts (unqid, title, link, content, user_id, user_nick, user_flair, 
                    tags, tags_details, likes, likes_details) 
                        SELECT , , , , 
                        , user_nick, user_flair, 
                        , , 1, 
                        from users where unqid = ;
                ELSE
                    RAISE EXCEPTION 'Fake tags detected!';
                END IF;
            END IF;
        ELSE
            RAISE EXCEPTION 'User is not logged in';
        END IF;
    END
    $$;"

DB.exec query, 
    session_id, session_user, tags_list, unqid, title, link, content, 
    tags_obj.to_json, tags_details_obj.to_json, likes_obj.to_json

当我使用字符串插值时,这个查询工作正常。但是当我尝试使用准备好的语句时,我开始得到;

bind message supplies 10 parameters, but prepared statement "" requires 0

如何在查询中使用准备好的语句?

您不能将 DO 语句用作准备好的语句。

我建议您使用两个语句:

  • 一个得到你需要判断是否有错误条件的三个结果

  • one to 运行 INSERT 语句

第二个是常规准备语句。

在我看来,您混淆了 PL/pgSQL 中的交易和 BEGIN ... END 区块。