PostgreSQL:CASE:从两个不同的表中选择

时间:2014-04-02 13:12:03

标签: sql postgresql select case create-function

  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. 相反,是否可以将command status string设置为-1?

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

4 个答案:

答案 0 :(得分:0)

除了{pl / pgsql} CASE expression之外还有一个CASE control structure

编辑:sql上下文中的CASE expression

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

编辑2 :给定your example,您可以在纯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

答案 1 :(得分: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

我想你可能想要研究创建一个返回函数的结果集。

答案 2 :(得分:0)

下面的PL / pgsql函数返回messages&之间发送的user_idwith_user_id如果user_idkey对已获得授权,则由用户定义的函数(UDF)user_auth确定。否则,它返回from = -1行。另一个UDF pairunique unordered pairing function,给定两个用户ID,返回消息所属的chat_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函数或者是否会更好。

答案 3 :(得分:0)

算法

  1. 如果我们找到1 - a匹配,请选择user_id_1session_id(已授权)。
  2. 如果我们在步骤1中找不到匹配项,请选择0, NULL, NULLu(未经授权)。
  3. 如果我们在步骤1中找到匹配项,请选择user_id, body, sents(选择)。
  4. 联盟us
  5. 代码

    -- 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;