Postgres: Хотите ВЫБРАТЬ данные, когда пользователь существует, иначе УКАЗАТЬ пользователя - PullRequest
1 голос
/ 20 февраля 2020

Все еще овладевает PostgreSQL (Используя PostgreSQL -12, поэтому любой совет очень высоко ценится.

У меня есть приложение, которое позволяет пользователю сохранять и создавать плейлисты песен.

Мои таблицы: пользователи, плейлисты, песни. Тогда у меня две соединительные таблицы: user_playlist, playlist_song

У меня есть запрос, который при получении идентификатора пользователя вернет все песни из первого плейлиста этого пользователя (приложение по умолчанию будет первым плейлистом при входе в систему), и в настоящее время он работает так, как я хочу.

Моя следующая проблема для решения является то, что я хочу теперь объединить этот запрос со вторым, который добавил бы идентификатор пользователя в пользовательскую таблицу, если он не существует в настоящее время.

Таким образом, поток будет вход пользователя в систему, а затем при входе в систему Идентификатор пользователя отправляется в мою базу данных. В моей базе данных я хочу проверить, существует ли уже этот идентификатор пользователя, если он мне нужен, чтобы запрос SELECT, возвращающий песни для выполнения, но если этот идентификатор пользователя не существует, я хочу вставить идентификатор пользователя в свой пользователь та ble

Я читал о 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

Я застрял в этом полтора дня и на данный момент и не хочу разбивать его на многократные звонки в БД, если это невозможно (моя гордость нуждается в squa sh этот подонок)

Я не могу сказать вам, сколько будет оценена ваша помощь! Заранее спасибо

РЕДАКТИРОВАТЬ: Вот мои таблицы

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;

1 Ответ

0 голосов
/ 20 февраля 2020

Создайте тип и затем верните его.

Я создал таблицу пользователей (ИД пользователя, имени пользователя), а затем создал тип с той же схемой, что и при выборе той же. Вам придется изменить его на столбцы, которые вы выбираете (при создании ТИПА).

Работает нормально.

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