【问题标题】:PostqreSQL Duplicate Values WHERE NOT EXISTSPostgreSQL 不存在的重复值
【发布时间】:2013-05-20 01:07:31
【问题描述】:

我编写了这段代码:

INSERT into author(authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
select '".addslashes($_POST['authorfirstname1'])."','".addslashes($_POST['authorlastname1'])."','".addslashes($_POST['authorfirstname2'])."','".addslashes($_POST['authorlastname2'])."'
from author
where not exists(select authorfirstname1, authorlastname1, authorfirstname2, authorlastname2 from author
where author.authorfirstname1='".addslashes($_POST['authorfirstname1'])."'
and author.authorlastname1='".addslashes($_POST['authorlastname1'])."'
and author.authorfirstname2='".addslashes($_POST['authorfirstname2'])."'
and author.authorlastname2='".addslashes($_POST['authorlastname2'])."'
);

这段代码的重点应该是它检查数据库中是否已经存在一个值,如果不存在,则输入它。 这个 '".addslashes($_POST['authorlastname2'])."' 代表一个输入,但可以很容易地替换为 '%myentereddata%'

我的问题是它没有做任何事情......甚至没有给出错误消息,它的成功,但是如果数据库中不存在数据,它不会输入数据并且不确定如果数据存在它是否停止输入数据。

因此,如果有人可以帮助我解决此代码的问题或提供另一个示例如何以不同的方式执行此操作,我将不胜感激。

我的id是primary和serial,所以不用插入

INSERT INTO author (authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
VALUES ('one','two','three','four');

查询成功返回:1 行受影响,60 毫秒执行时间。

INSERT into author(authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
select 'one','two','three','four'
from author
where not exists(select authorfirstname1, authorlastname1, authorfirstname2, authorlastname2 from author
where author.authorfirstname1='one'
and author.authorlastname1='two'
and author.authorfirstname2='three'
and author.authorlastname2='four'
);

查询成功返回:657 行受影响,40 毫秒执行时间。

INSERT into author(authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
select 'new','new','new','new'
from author
where not exists(select authorfirstname1, authorlastname1, authorfirstname2, authorlastname2 from author
where author.authorfirstname1='new'
and author.authorlastname1='new'
and author.authorfirstname2='new'
and author.authorlastname2='new'
);

查询成功返回:1314 行受影响,70 毫秒执行时间。

【问题讨论】:

  • 如果您尝试插入已经存在的行,您想得到错误吗?还是如果它不存在就插入它,如果它已经存在则安静地忽略它?

标签: postgresql sql-insert not-exists


【解决方案1】:

问题是有两个 FROM 子句而不是一个。实际上,您插入同一行的次数与整个表中的行数一样多(当满足 WHERE 子句时)。 查询应该是(请注意,与您的版本相比,第一个 FROM 已被删除):

INSERT into author(authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
select 'one','two','three','four'
where not exists(select 1 from author
where author.authorfirstname1='one'
and author.authorlastname1='two'
and author.authorfirstname2='three'
and author.authorlastname2='four'
);

内部选择中的列也已被删除。 SELECT 1 FROM... 足以检查是否存在行,无需提取特定列,它们无论如何都会在上层被丢弃。

另一个不相关的问题是,只要任何注入的参数包含引号字符,使用addslashes 完成的转义就会产生无效的查询。

这是因为当 PG 的 standard_conforming_strings 设置为 ON 时,反斜杠是一个正常字符,不会转义任何内容。从 PostgreSQL 9.1 开始,默认开启。

请改用pg_escape_string

【讨论】:

  • @mudsao 那么请将此答案标记为正确(左侧数字下方的钩子)
【解决方案2】:

如果您只想确定表中没有重复条目,您应该使用UNIQUE

这样,每当你INSERT 一个已经存在的行时,你就会得到一个错误。

像这样:

CREATE UNIQUE INDEX ON author (authorfirstname1, authorlastname1, authorfirstname2, authorlastname2);

之后,您将无法 INSERT 同一组名字和姓氏两次。

你然后INSERT这样:

INSERT into author(authorfirstname1, authorlastname1,authorfirstname2, authorlastname2)
VALUES ('".addslashes($_POST['authorfirstname1'])."', '".addslashes($_POST['authorlastname1'])."', '".addslashes($_POST['authorfirstname2'])."', '".addslashes($_POST['authorlastname2'])."')

【讨论】:

  • 这是我在使用数据库中没有的值时得到的结果:查询成功返回:606208 行受影响,18829 毫秒执行时间。 (没有输入任何内容)这就是我再次使用相同值得到的结果:查询成功返回:1212416 行受影响,41933 毫秒执行时间。 (仍然没有条目......)可能是我的 postgresql 问题,使用 PostgreSQL 9.1
  • 您提交交易了吗?
  • @mudsao 您打算插入 600.000 条新行吗?还是只想插入一行?
  • @mudsao 这不是错误。您的代码可以正常工作,但我怀疑它是否符合您的要求。所以请回答我的其他cmets。
  • @Angelo:多次运行你的最后一个查询,你会看到每次它插入的不是一行而是表的行数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 2021-04-30
  • 2020-12-19
  • 2021-04-05
  • 2021-12-01
相关资源
最近更新 更多