首页 > 解决方案 > Postgres:想要在用户存在时选择数据,否则插入用户

问题描述

仍然掌握 PostgreSQL 的窍门(使用 PostgreSQL-12,因此非常感谢任何建议。

我有一个允许用户保存和创建歌曲播放列表的应用程序。

我的表是:用户、播放列表、歌曲然后我有两个联结表: user_playlist、playlist_song

我有一个查询,当给定用户 ID 时,将返回该用户的第一个播放列表中的所有歌曲(应用程序默认为登录时的第一个播放列表),并且它目前按我想要的方式工作。

我要解决的下一个问题是,我现在想将该查询与第二个查询结合起来,如果它当前不存在,它将把用户 ID 添加到用户表中。

因此流程将是用户登录,然后在登录时将用户 ID 发送到我的数据库。在我的数据库中,我想检查该用户 ID 是否已经存在,如果存在,我希望执行返回歌曲的 SELECT 查询,但如果该用户 ID 不存在,我想将该用户 ID 插入到我的用户表中

我已经阅读了大约 10 个 StackOverflow 解决方案,试图调整它们为我工作,但没有任何运气。我不确定我是否应该发布我已经尝试过的所有东西。

$$ BEGIN
      IF EXISTS (SELECT 1 FROM users WHERE userid = '1') THEN

        SELECT
          s.songid,
          s.title,
          s.artists,
          s.album,
          s.year,
          s.duration,
          s.url,
          ps.songOrder
        FROM
          playlist_song ps
        JOIN
          songs s
        ON
          ps.songid = s.songid
        JOIN
          playlists p
        ON
          ps.playlistid = p.playlistid
        WHERE
          p.playlistid = (
            SELECT
              p.playlistid
            FROM
              user_playlist up
            JOIN
              playlists p
            ON
              up.playlistid = p.playlistid
            JOIN
              users u
            ON
              up.userid = u.userid
            WHERE
              u.userid = '1'
            LIMIT 1
          )
        ORDER BY ps.songOrder;


    ELSE
      INSERT INTO users (userid, username) VALUES ('1', 'Haley')
        ON CONFLICT DO NOTHING;
    END IF;
END $$;

这是我在 PG admin 中测试它时当前给我的错误:

ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT:  PL/pgSQL function inline_code_block line 4 at SQL statement
SQL state: 42601

所以我然后将 RETURN 添加到我的 SELECT 中,错误更改为

LINE 5:         RETURN (SELECT
                       ^
SQL state: 42804
Character: 98

添加 RETURN QUERY 给出的错误是不能在非 setof 函数中使用返回查询

添加 RETURN SETOF 给出的错误是 RETURN 在返回 void 的函数中不能有参数

我已经坚持了一天半,在这一点上,我不想将它分解为对数据库的多次调用,除非这是不可能的(我的骄傲需要压扁这个臭虫)

我不能告诉你有多少你的帮助将不胜感激!提前致谢

编辑:这是我的桌子

CREATE TABLE IF NOT EXISTS users (
      userid TEXT NOT NULL,
      username TEXT NOT NULL,
        CONSTRAINT u_id_pk PRIMARY KEY (userid)
    );


    CREATE TABLE IF NOT EXISTS playlists (
      playlistid SERIAL NOT NULL,
      playlistname TEXT NOT NULL,
        CONSTRAINT p_id_pk PRIMARY KEY (playlistid)

    );

    CREATE TABLE IF NOT EXISTS songs (
      songid SERIAL NOT NULL,
      url TEXT,
      href TEXT,
      title TEXT,
      artists TEXT,
      album TEXT,
      year integer,
      duration integer,
        CONSTRAINT s_pk PRIMARY KEY (songid)
    );

    CREATE TABLE IF NOT EXISTS user_playlist (
      userid TEXT,
      playlistid INTEGER,
        CONSTRAINT u_up_fk FOREIGN KEY (userid) REFERENCES users(userid),
        CONSTRAINT p_up_fk FOREIGN KEY (playlistid) REFERENCES playlists(playlistid)
    );

    CREATE TABLE IF NOT EXISTS playlist_song (
      playlistid INTEGER,
      songid INTEGER,
      songOrder INTEGER,
        CONSTRAINT p_ps_fk FOREIGN KEY (playlistid) REFERENCES playlists(playlistid),
        CONSTRAINT s_ps_fk FOREIGN KEY (songid) REFERENCES songs(songid)
    );

下一次尝试

CREATE TYPE songs_type AS (
          songid integer,
          title character varying(25),
          artists character varying(25),
          album character varying(25),
          year integer,
          duration integer,
          url character varying(25),
          songOrder integer
);

CREATE OR REPLACE FUNCTION func() RETURNS songs_type AS
$$
DECLARE results_record songs_type;
BEGIN
    IF EXISTS (SELECT 1 FROM auxium.users WHERE userid = '1') THEN

      SELECT
          s.songid,
          s.title,
          s.artists,
          s.album,
          s.year,
          s.duration,
          s.url,
          ps.songOrder


        INTO
          results_record.songid,
          results_record.title,
          results_record.artists,
          results_record.album,
          results_record.year,
          results_record.duration,
          results_record.url,
          results_record.songOrder
        FROM
          auxium.playlist_song ps
        JOIN
          auxium.songs s
        ON
          ps.songid = s.songid
        JOIN
          auxium.playlists p
        ON
          ps.playlistid = p.playlistid
        WHERE
          p.playlistid = (
            SELECT
              p.playlistid
            FROM
              auxium.user_playlist up
            JOIN
              auxium.playlists p
            ON
              up.playlistid = p.playlistid
            JOIN
              auxium.users u
            ON
              up.userid = u.userid
            WHERE
              u.userid = '1'
            LIMIT 1
          )
        ORDER BY ps.songOrder;


    ELSE
      INSERT INTO auxium.users (userid, username) VALUES ('1', 'Haley')
        ON CONFLICT DO NOTHING;
    END IF;
    return results_record;
END;
$$

LANGUAGE plpgsql;

标签: sqlpostgresqlpostgresql-12

解决方案


创建类型,然后返回它。

我创建了 users(userid,username) 表,然后创建了与我选择相同模式的类型。您必须将其更改为您正在选择的列(在创建 TYPE 时)。

它工作正常。

CREATE TYPE users_type AS (userid integer,username character varying(10));

CREATE OR REPLACE FUNCTION fun() RETURNS users_type AS
$$ 
DECLARE result_record users_type;
BEGIN
    IF EXISTS (SELECT 1 FROM users WHERE userid = 1) THEN
         SELECT userid,username into result_record.userid,result_record.username from users;
    ELSE
      INSERT INTO users (userid, username) VALUES (1, 'Haley');
    END IF;
    return result_record;
END;
$$

LANGUAGE plpgsql;

推荐阅读