当前位置: 首页 > 知识库问答 >
问题:

插入冲突时什么都不做-读取csv并生成外键表

邵毅
2023-03-14

我试图在csv文件中读取列艺术家,专辑,歌曲和标签

我希望像这样填充artist_album_song表:

|artist_id|album_id|song_id|
|---------|--------|-------|
|   1     |     1  |     1 |
|   1     |     1  |     2 |
|   1     |     2  |     1 |
...
|  12     |     1  |     1 |
...

我已经设计并正在尝试填充以下表。问题是填充artist_album_song表中的外键,就像我在csv中读到的那样。

插入到这个表中的最佳方法是什么,它可以实现我在下面使用的INSERT语句中尝试做的事情(返回语法错误)?谢谢。

create table artists (
    artist_id SERIAL PRIMARY KEY,
    artist VARCHAR(100) NOT NULL UNIQUE
);

create table albums (
    album_id SERIAL PRIMARY KEY,
    album VARCHAR(100) NOT NULL UNIQUE
);

create table songs (
    song_id SERIAL PRIMARY KEY,
    song VARCHAR(250) NOT NULL UNIQUE
);

create table tags (
    tag_id SERIAL PRIMARY KEY,
    tag VARCHAR(100) NOT NULL UNIQUE
);

create table artists_albums_songs (
    artist_id INTEGER NOT NULL,
    album_id INTEGER NOT NULL,
    song_id INTEGER NOT NULL,
    FOREIGN KEY (artist_id) REFERENCES artists(artist_id),
    FOREIGN KEY (album_id) REFERENCES albums(album_id),
    FOREIGN KEY (song_id) REFERENCES songs(song_id),
    PRIMARY KEY (artist_id, album_id, song_id)
);

create table songs_tags (
    song_id INTEGER NOT NULL,
    tag_id INTEGER NOT NULL,
    FOREIGN KEY (song_id) REFERENCES songs(song_id),
    FOREIGN KEY (tag_id) REFERENCES tags(tag_id),
    PRIMARY KEY (song_id, tag_id)
);

在尝试了下面链接中各种不同的语句后,我仍然无法让它发挥作用。

我尝试了以下语句,但总是出错。第一个返回错误:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "ON" Position: 161;

161是否指下面SQL语句中的第161个字符?

INSERT INTO artists_albums_songs
SELECT artist_id, album_id, song_id 
FROM artists a 
    JOIN albums b
        ON a.artist = ?
        AND b.album = ?
    JOIN songs c
        ON c.song = ?
    ON DUPLICATE (artist_id, album_id, song_id) DO NOTHING;

INSERT INTO artists_albums_songs
SELECT artist_id, album_id, song_id 
FROM artists a 
    JOIN albums b
        ON a.artist = ?
        AND b.album = ?
    JOIN songs c
        ON c.song = ?
    WHERE NOT EXISTS (
        SELECT * 
        FROM artists_albums_songs
        WHERE * = ?, ?, ?)

INSERT INTO artists_albums_songs
SELECT artist_id, album_id, song_id 
FROM artists a 
    JOIN albums b
        ON a.artist = ?
        AND b.album = ?
    JOIN songs c
        ON c.song = ?
    ON CONFLICT (song_id) IGNORE;

编辑:如果我删除上面3个INSERT语句的最后一行,它就可以工作,但是当它遇到一个重复的语句时,它会说:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "artists_albums_songs_pkey"
  Detail: Key (artist_id, album_id, song_id)=(1, 1, 1) already exists.

在PostgreSQL中重复更新时插入?

使用插入。。。在冲突时不执行任何操作返回失败的行

如何在PostgreSQL中升级(合并、插入…重复更新)?

共有2个答案

汪鸿波
2023-03-14

此行错误:

 ON DUPLICATE (artist_id, album_id, song_id) DO NOTHING;

Postgtresql在冲突上使用关键字https://www.postgresql.org/docs/current/static/sql-insert.html

秦皓君
2023-03-14

编辑1:我刚刚意识到我可以用Java处理这些错误!因此,我的解决方案就是添加一个catch语句来处理重复的SQLException

private <T> void insertIntoArtistAlbumSong(T artist, T album, T song) throws SQLException {

    try {

        String artString = artist.toString();
        String albString = album.toString();
        String songString = song.toString();

        // Create SQL insert statement
        String stm =
                "INSERT INTO artists_albums_songs " +
                        "SELECT artist_id, album_id, song_id " +
                        "FROM artists a " +
                        "JOIN albums b " +
                        "ON a.artist = ? " +
                        "AND b.album = ? " +
                        "JOIN songs c " +
                        "ON c.song = ? ;";


        PreparedStatement pstmt = connection.prepareStatement(stm);

        // Set values in prepared statement
        pstmt.setString(1, artString);
        pstmt.setString(2, albString);
        pstmt.setString(3, songString);

        // Insert into table
        pstmt.executeUpdate();

    // ADDED THIS CATCH STATEMENT!
    } catch (SQLException e){
        System.out.println(e.getSQLState());
    }
}

好的,我找到了一个解决方案,但它只适用于填充表(这是我实际需要做的全部)。

>

  • 删除原始artists_albums_songs[1]表
  • 创建不带约束的新artists_albums_songs[2]表:

    CREATE TABLE artists_albums_songs (
        artist_id INTEGER NOT NULL,
        album_id INTEGER NOT NULL,
        song_id INTEGER NOT NULL
    );
    

    然后,我用以下语句(通过JDBC)填充新表[2]:

    INSERT INTO artists_albums_songs
    SELECT artist_id, album_id, song_id 
    FROM artists a 
        JOIN albums b
            ON a.artist = ?
            AND b.album = ?
        JOIN songs c
            ON c.song = ?;
    

    创建一个带有约束的tmp[3]表(通过psql命令行):

    CREATE TABLE tmp (
        artist_id INTEGER NOT NULL,
        album_id INTEGER NOT NULL,
        song_id INTEGER NOT NULL,
        FOREIGN KEY (artist_id) REFERENCES artists(artist_id),
        FOREIGN KEY (album_id) REFERENCES albums(album_id),
        FOREIGN KEY (song_id) REFERENCES songs(song_id),
        PRIMARY KEY (artist_id, album_id, song_id)
    );
    

    仅将新的艺术家_专辑_歌曲[2]中不同的行插入tmp[3](通过psql):

    INSERT INTO tmp SELECT DISTINCT * FROM artists_albums_songs
    ORDER BY artist_id, album_id, song_id ASC;
    

    删除新的artists_albums_songs[2]并将tmp[3]重命名为artists_albums_songs(通过psql):

    DROP TABLE artists_albums_songs;
    ALTER TABLE tmp RENAME TO artists_albums_songs;
    

  •  类似资料:
    • 在迁移程序中,我对表_1执行插入查询,其定义如下: 现在,当我尝试插入此表时,我得到以下错误: 事务错误中的错误:在表"table_1"上插入或更新违反外键约束"table_2_fkey" 我尝试在以下表单中执行插入查询: 有没有办法防止违反外键约束(跳过它们)? 类似。 注意:它不违反第二个外键约束,因为我将此表(table_2)中的数据填充为我试图填充到table_1的行(用于规范化)。tab

    • 这是我的第一个JMH基准测试。我可能做错了一切,但是... 我的基准看起来是这样的 是我开始的...等了又等,然后杀了它。我怀疑在< code>@Setup中有问题,所以我简化了它,但是什么都没有改变。这场赛跑开始时相当乐观... 然后什么都没发生。过了很长时间,它继续写下20行像 和5行像 然后它输出一些结果 并更正其估计的eta: 我的是否比我想象的更频繁地被调用,或者还有什么其他原因导致了缓

    • 我制作了一个git存储库,并向其中添加了一个文本文件。这是100%用于学习目的。 > 从master创建了一个新分支,并附加了“2”。 最后,从master创建了一个分支并添加了“3”。 请您解释一下在这种或任何其他情况下,冲突是如何发生的?

    • 在Java中,什么与Python的pass等效?我意识到我可以使用continue语句或不完成语句体来实现这种效果,但我喜欢使用pass语句。

    • 我的配置文件是类路径的路径。至少我认为是这样。我放置了log4j。资源文件夹中的属性文件,而log4j对此不做任何处理。即使我删除了它,也不会发生错误。 任何人都可以看到,我在使用maven LoggerTest的内容: 程序输出: log4j的内容。属性: 在波姆。xml并不是什么不同寻常的东西,只是一个依赖组织。阿帕奇。登录中。log4j log4j内核2.17.2,编译器源目标是16,没有插

    • 我正在从国家美术馆的在线目录中检索信息。由于目录的结构,我无法通过提取和跟踪条目之间的链接来导航。幸运的是,集合中的每个对象都有一个可预测的url。我希望我的爬行器通过生成开始URL来导航集合。 我试图通过实现这个线程中的解决方案来解决我的问题。不幸的是,这似乎打破了我蜘蛛的另一部分。错误日志显示我的网址正在成功生成,但它们没有被正确处理。如果我正确地解释了日志——我怀疑我没有——在重新定义允许我