3
  1. 是否可以使用 SQL 而不是 PL/pgSQL 执行以下操作(请注意,如果它只能使用 PL/pgSQL,那么如何)?

    IF password = 'swordfish' THEN
        SELECT a, b, c FROM users;
    ELSE
        SELECT -1; -- unauthorized error code
    END IF;
    
  2. 理想情况下,我可以将上述内容包装在一个TRUE作为参数的函数中吗?

  3. 相反,是否可以将命令状态字符串设置为 -1?

我问这个是因为我希望查询返回一个错误代码,比如 -1,如果有人试图获取所有密码错误的用户的列表。这适用于具有用户帐户的 Web 应用程序,每个用户帐户都有一个密码。所以,这不是我想用数据库角色/权限管理的东西。

4

4 回答 4

2

算法

  1. 如果我们找到-匹配项,请选择1进入(授权)。auser_id_1session_id
  2. 如果我们在步骤 1 中没有找到匹配项,请选择0, NULL, NULL进入(未经授权)。u
  3. 如果我们在步骤 1 中确实找到了匹配项,请选择user_id, body, sent进入(选择)。s
  4. 联合us

代码

-- List messages between two users with `user_id_1`, `session_id`, `user_id_2`
CREATE FUNCTION messages(bigint, uuid, bigint) RETURNS TABLE(i bigint, b text, s double precision) AS
$$
    WITH a AS (
        SELECT 1
        FROM sessions
        WHERE user_id = $1
        AND id = $2
    ), u AS (
        SELECT 0, NULL::text, NULL::double precision
        WHERE NOT EXISTS (SELECT 1 FROM a)
    ), s AS (
        SELECT user_id, body, trunc(EXTRACT(EPOCH FROM sent))
        FROM messages
        WHERE EXISTS (SELECT 1 FROM a)
        AND chat_id = pair($1, $3)
        LIMIT 20
    )
    SELECT * FROM u UNION ALL SELECT * FROM s;
$$
LANGUAGE SQL STABLE;
于 2014-05-07T01:31:24.647 回答
0

这会起作用,但它并不漂亮:

WITH 
  u AS (SELECT * FROM user WHERE mail = '..'),
  code AS (
    SELECT 
      CASE (SELECT count(*) FROM u)
      WHEN 0 THEN
        'not found'
      ELSE
        CASE (SELECT count(*) FROM u WHERE password = '..')
        WHEN 1 THEN
          'right password'
        ELSE
          'wrong password'
        END
      END)
SELECT
  code.*,
  u.*
FROM code NATURAL LEFT OUTER JOIN u

我认为您可能想考虑创建一个结果集返回函数。

于 2014-04-02T14:01:32.727 回答
0

如果:对被授权,则下面的 PL/pgsql 函数返回在&messages之间发送的值,由用户定义函数 (UDF) 确定。否则,它返回一行。另一个 UDF是一个唯一的无序配对函数,给定两个用户 ID,返回消息所属的。user_idwith_user_iduser_idkeyuser_authfrom = -1pairchat_id

--- Arguments: user_id, key, with_user_id
CREATE FUNCTION messages(bigint, uuid, bigint)
RETURNS TABLE(from bigint, body text, sent double precision) AS $$
BEGIN
    IF user_auth($1, $2) THEN
        RETURN QUERY SELECT from, body, trunc(EXTRACT(EPOCH FROM sent))
                     FROM messages WHERE chat_id = pair($1, $3);
    ELSE
        i := -1;
        RETURN NEXT;
    END IF;
END;
$$ LANGUAGE plpgsql STABLE;

我不知道如何将其转换为 SQL 函数或是否会更好。

于 2014-04-02T15:53:07.430 回答
0

除了(pl/pgsql only)控制结构之外,还有一个CASE表达式CASE

编辑:sql上下文中的CASE表达式:

SELECT CASE
           WHEN my_conditions_are_met THEN a
           ELSE NULL
       END AS a_or_null,
       b,
       c
FROM users;

编辑2:给定你的例子,你可以在纯SQL中做到这一点:

WITH params AS (
    SELECT user_auth(:user_id, :key)     AS user_auth,
           pair(:user_id, :with_user_id) AS chat_id
), error_message AS (
    SELECT -1                                    AS "from",
           'auth error'                          AS "body",
           EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) AS "sent"
)
SELECT from, body, trunc(EXTRACT(EPOCH FROM sent))
FROM messages
JOIN params ON messages.chat_id = params.chat_id AND params.user_auth
UNION ALL
SELECT error_message.*
FROM error_message
JOIN params ON NOT params.user_auth
于 2014-04-02T13:21:09.990 回答