POSTGRESQL从给定的JSON数组插入多行,使用insert的结果执行其他插入操作

问题描述 投票:0回答:1

TL; DR音乐流媒体应用-允许用户上传自己的文件。文件将存储在FileSet中。我想传入一个以上的FILESET数组,并插入到适当的表中。

抱歉,这有点令人困惑-基本上我正在使用3个表:

文件表

CREATE TABLE file
(
    -- Most tables should have a table_id & table_cuid
    file_id         BIGSERIAL   NOT NULL ,
    file_cuid       VARCHAR     NOT NULL,

    -- This section is specific to this table
    user_id         BIGINT      NOT NULL,

    -- File fields
    filename        VARCHAR     NOT NULL,
    last_modified   TIMESTAMP WITHOUT TIME ZONE NOT NULL,
    size_in_bytes   VARCHAR     NOT NULL,
    mime_type       VARCHAR     NOT NULL,

    -- Most tables should also have timestamps
    created_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,
    updated_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,

    -- Constraints
    PRIMARY KEY (file_id),
    FOREIGN KEY (user_id)   REFERENCES users (user_id),
    CONSTRAINT file_cuid_unique  UNIQUE     (file_cuid)
)

文件集表

CREATE TABLE fileset
(
    -- Most tables should have a table_id & table_cuid
    fileset_id         BIGSERIAL   NOT NULL ,
    fileset_cuid       VARCHAR     NOT NULL,

    user_id         BIGINT      NOT NULL,

    -- Fileset fields TBD

    created_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,
    updated_timestamp  TIMESTAMP WITHOUT TIME ZONE  NOT NULL,

    -- Constraints
    PRIMARY KEY (fileset_id),
    FOREIGN KEY (user_id)   REFERENCES users (user_id),
    CONSTRAINT cuid_unique_fileset  UNIQUE     (fileset_cuid)
)

最后是File_FileSet_Rel Table

CREATE TABLE file_fileset_rel
(
    file_id         BIGSERIAL   NOT NULL,
    fileset_id      BIGSERIAL   NOT NULL,

    FOREIGN KEY (file_id)  REFERENCES file   (file_id),
    FOREIGN KEY (fileset_id)   REFERENCES fileset (fileset_id),
    UNIQUE      (file_id, fileset_id)
)

每首歌曲将具有一个与之关联的文件集,并且该文件集具有一个/多个文件。

下面的函数(file_upload_process)允许我将File添加到表中(返回file_id),以及将Fileset添加到表中(返回fileset_id),最后该函数同时插入了两者这些值放入最终表file_fileset_rel

file_upload_process.sql

CREATE OR REPLACE FUNCTION file_upload_process(
  _file_cuid VARCHAR,
  _fileset_cuid VARCHAR,
  _cognito_id VARCHAR,
  _name VARCHAR,
  _last_modified TIMESTAMP,
  _size DECIMAL,
  _type VARCHAR
)
RETURNS TABLE(
  fileId BIGINT,
  fileSetID BIGINT
)
AS $file_upload_process$
DECLARE
v_user_id BIGINT;
v_file_id BIGINT;
v_fileset_id BIGINT;
BEGIN

-- Create Song/ Update song
  -- store user_id
  v_user_id := (
    SELECT * FROM get_user_id(_cognito_id)
  );

  -- --Insert In FILE table
  v_file_id := (
    SELECT *
    FROM create_file(
    _file_cuid,
    v_user_id,
    _name,
    _last_modified,
    _size,
    _type
    )
  );

  --Insert into fileset table
  v_fileset_id := (
  SELECT * FROM create_fileset(_fileset_cuid, v_user_id)
  );

  RETURN QUERY
  INSERT INTO file_fileset_rel(file_id, fileset_id)
  VALUES (
    v_file_id,
    v_fileset_id
  )
  RETURNING file_fileset_rel.file_id,
            file_fileset_rel.fileset_id;
END;
$file_upload_process$ LANGUAGE PLPGSQL;

其中调用以下功能:

create_file.sql

CREATE OR REPLACE FUNCTION create_file(
  _file_cuid VARCHAR,
  _user_id BIGINT,
  _name VARCHAR,
  _last_modified TIMESTAMP,
  _size DECIMAL,
  _type VARCHAR
)
RETURNS TABLE (
  _file_id BIGINT
)
AS $create_file$
BEGIN
  RETURN QUERY
-- Create Song/ Update song
  INSERT INTO file(
    file_cuid,
    user_id,
    filename,
    last_modified,
    size_in_bytes,
    mime_type,
    created_timestamp,
    updated_timestamp
  )
  VALUES(
    _file_cuid,
    _user_id,
    _name,
    _last_modified,
    _size,
    _type,
    now(),
    now()
  )
  RETURNING "file".file_id;
END;
$create_file$ LANGUAGE PLPGSQL;

和create_fileset函数:

    CREATE OR REPLACE FUNCTION create_fileset(
  _fileset_cuid VARCHAR,
  _user_id BIGINT
)
RETURNS TABLE (
  _fileset_id BIGINT
)
AS $create_fileset$
BEGIN
-- Create Song/ Update song
  RETURN QUERY
  INSERT INTO fileset(
    fileset_cuid,
    user_id,
    created_timestamp,
    updated_timestamp
  )
  VALUES(
    _fileset_cuid,
    _user_id,
    now(),
    now()
  )
  RETURNING "fileset".fileset_id;
END;
$create_fileset$ LANGUAGE PLPGSQL;

我遇到的问题是,此功能一次只能添加1个文件,用户可以为1首歌曲(1个文件集)上传5-10个文件,所以我需要一种方法来遍历fileRecords数组并将这些字段的值存储在FILE表列中-最终允许我向file_fileset_rel表中添加多个记录。

[如果有人有更轻松的方法来完成所有这些工作,或更重要的是,对MANY vs One插入物的解决方案将是巨大的帮助。

编辑:CURRENT主体发送到lambda的示例-传递给postgresql函数之前网址->文件集/ {filesetCuid} /文件

body: {
"cognitoId" : "9dc766a0-c5c9-4455-932e-46c243c80266",
"fileRecord" : {
    "fileCuid" : "someotherfilecuid23",
    "name" : "file_name",
    "last_modified" : "06/03/1995",
    "size" : 530,
    "type" : "mp3/audio"
}
}

最终目标-发送多个文件:网址->文件集/ {filesetCuid} /文件

body: {
"cognitoId" : "9dc766a0-c5c9-4455-932e-46c243c80266",
"fileRecords" : [{
    "fileCuid" : "someotherfilecuid23",
    "name" : "file_name",
    "last_modified" : "06/03/1995",
    "size" : 530,
    "type" : "mp3/audio"
}, {...}, {...}]
}
postgresql plpgsql stored-functions
1个回答
0
投票

[您可以从this PostgREST issue中采用一种优雅的解决方案。您还可以在LOOP中使用LOOP来包装所有函数调用。

前者更好,因为它是一个很好的多合一逻辑:

  • 它取决于目标表的定义(例如,在运行中设置file_upload_process.sql值)
  • 您可以直接传递JSON数组(即您may忽略不需要的值)
  • 您可以根据您的DEFAULT约束处理冲突(并自动检索现有行的UNIQUE!]
© www.soinside.com 2019 - 2024. All rights reserved.