【问题标题】:Fill a table with elements from another table用另一个表中的元素填充一个表
【发布时间】:2018-02-22 14:10:12
【问题描述】:

我的 java 项目有问题。我有两个文本文件要使用 jdbc 驱动程序插入到 postgresql 中。这两个文件属于这种类型: 1) snp (rsid, chr, 布尔值) 2)基因座(rsid、mrna、基因、类)

我必须得到两个这种类型的表: 1)Snp (id 序列号, rsid varchar, chr varchar, has_sig boolean) 2)Locus (id serial, mana_acc varchar,gene varchar,class varchar,snp_id integer) 其中轨迹的 snp_id 是对 Snp(id) 的外键引用。

我可以用来连接表的字段是 rsid,这对两个文件都是通用的。

我是这样创建表格的:

st = connection.prepareStatement(
                "CREATE TABLE IF NOT EXISTS snp ("
                + "id SERIAL PRIMARY KEY, "
                + "rsid varchar(100), "
                + "chr varchar(100), "
                + "has_sig varchar(100))");
        st.executeUpdate();
        st.close();

        st = connection.prepareStatement(
                "CREATE TABLE IF NOT EXISTS locus ("
                + "id SERIAL PRIMARY KEY, "
                + "rsid varchar(100), "
                + "mrna_acc varchar(100), "
                + "gene varchar(100), "
                + "class varchar(100), "
                + "snp_id integer REFERENCES snp(id) on delete cascade on update cascade)");
        st.executeUpdate();
        st.close();

然后我使用 select 查询而不是 snp_id 字段将文件放入表中:

FileSnp fs = new FileSnp("/Users/valentinafratini/Documents/Progetto Tesi/FactoryMethodDb/snp.csv");
        fs.readFile();
        while (fs.line!=null) {
            fs.line = fs.reader.readLine();

            if (fs.line!=null && fs.line.length()>0) {
                    fs.obj = fs.line.split("\\s+");
                    fs.readSingleObj();

                    st = connection.prepareStatement("INSERT INTO snp ("
                        + "id, "
                        + "rsid, "
                        + "chr, "
                        + "has_sig) "
                        + "VALUES (DEFAULT, ?, ?, ?)");
                    st.setString(1, fs.rsid);
                    st.setString(2, fs.chr);
                    st.setString(3, fs.has_sig);
                    st.executeUpdate(); 
                    st.close();

FileLocus fl = new FileLocus("/Users/valentinafratini/Documents/Progetto Tesi/FactoryMethodDb/locus.csv");
        fl.readFile();
        while (fl.line!=null) {
            fl.line = fl.reader.readLine();

            if (fl.line!=null && fl.line.length()>0) {
                    fl.obj = fl.line.split("\\s+");
                    fl.readSingleObj();

                    st = connection.prepareStatement("INSERT INTO locus ("
                        + "id, "
                        + "rsid, "  
                        + "mrna_acc, "
                        + "gene, "
                        + "class,"
                        + "snp_id) "
                        + "VALUES (DEFAULT, ?, ?, ?, ?, (SELECT id FROM snp s WHERE rsid = s.rsid))");
                    st.setString(1, fl.rsid);
                    st.setString(2, fl.mrna_acc);
                    st.setString(3, fl.gene);
                    st.setString(4, fl.classe);
                    st.executeUpdate();
                    st.close();

但是当我填写时出现以下错误:

错误:用作表达式的子查询返回多于一行

你能帮帮我吗? 非常感谢。

【问题讨论】:

  • 错误信息很清楚——子查询返回多于1行。要么让它返回最多一行,要么做 INSERT ... SELECT ...
  • 我在两个不同的查询中是否有 insert.. select..?

标签: sql postgresql


【解决方案1】:

似乎rsid 在表snp 中不是唯一的。这会导致子查询

SELECT id FROM snp s WHERE rsid = s.rsid

返回多行,这是错误的原因。

我建议您使用INSERT ... RETURNING 来获取输入到snp 的行的id

INSERT INTO snp (id, ...)
VALUES (DEFAULT, ...)
RETURNING id;

然后将返回值绑定到以下查询中的占位符:

INSERT INTO locus (..., snp_id)
VALUES (..., ?);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多