带有 INSERT 和 WHERE NOT EXISTS 的奇怪 SQL 行为
Posted
技术标签:
【中文标题】带有 INSERT 和 WHERE NOT EXISTS 的奇怪 SQL 行为【英文标题】:Weird SQL behavior with INSERT and WHERE NOT EXISTS 【发布时间】:2011-06-10 15:59:26 【问题描述】:我有这个查询,如果表中不存在相同 ID 的等于或更高的金额,它应该插入一个金额。
我在 mysql 5.1 和 MSSQL 2k5 下试过这个:
MySQL
INSERT IGNORE INTO 测试(ID、金额) 从测试中选择 6、50 WHERE NOT EXISTS (SELECT 1 from test WHERE amount >= 50 AND id = 6) LIMIT 1
MSSQL
INSERT INTO 测试(ID、金额) 从测试中选择 6、50 WHERE NOT EXISTS (SELECT TOP 1 1 FROM test WHERE amount >= 50 AND id = 6)
如果表中已经至少有一个条目,则此查询可以正常工作。如果表是空的,它将永远无法工作。在 MySQL (5.1) 和 MSSQL (2005) 下的行为相同。 我不明白为什么。即使表完全为空,任何人都有解释和方法来修复此查询以使其正常工作?
编辑:我主要需要这个用于 MySQL...
更新:我专门针对 MySQL 提出了一个新问题: MySQL Problem with inserting a row with certain conditions
【问题讨论】:
是 SELECT TOP 1 1 = SELECT TOP 1 * ? @Chris 我认为是这样,在“exists(select...”中我认为不需要顶部,也不需要 1。 我仍然无法让它在 MySQL 下工作......如果你有其他方法也可以。也许左连接可以工作? 【参考方案1】:失败是因为 select 语句根据返回的行数选择了 6 和 50 的值。由于您的表是空的 - 不会返回任何具有这些值的行。
修改为
INSERT INTO test (id, amount) SELECT 6, 50 WHERE NOT EXISTS (SELECT TOP 1 1 FROM test WHERE amount >= 50 AND id = 6)
【讨论】:
它在 MySQL 中不起作用......它不喜欢 WHERE 之前没有 FROM 子句:( 在 MySQL 下不起作用。不能缺少 FROM 子句,如果添加它,在没有行的情况下仍然是同样的问题... 我接受了它,因为它在 MSSQL 下工作,而我对 MySQL 不够精确。我为 MySQL 提出了一个新问题,请在我的帖子中查看更新以获取链接。谢谢:) 似乎倒退了“编辑:我主要需要这个用于 MySQL...” 如果添加“FROM DUAL”,它可以在 MySQL 上运行 - DUAL 显然就像一个虚拟表,它总是像只有一行一样。【参考方案2】:如下更改您的查询:
INSERT INTO test (id, amount)
SELECT 6, 50 FROM test
WHERE (SELECT count(*) FROM test WHERE amount >= 50 AND id = 6) = 0
【讨论】:
当表为空时影响 0 行:|当表格中至少有一行时工作......奇怪的胡:P 这不像预期的那样工作,我已经测试并得到了另一个解决方案【参考方案3】:我一步一步尝试了这个:
-- create a test-table with one entry
SELECT id = 1, amount = 50
into #TEST
-- see if statement works when table is not empty
INSERT INTO #test (id, amount)
SELECT id = 6, amount = 50
FROM #test
WHERE NOT EXISTS (SELECT * FROM #test WHERE amount >= 50 AND id = 6)
-- show content of test-table
select * from #test
-- empty the test table
truncate table #test
-- try to insert a first dataentry
INSERT INTO #test (id, amount)
SELECT id = 6, amount = 50
FROM #test
WHERE NOT EXISTS (SELECT * FROM #test WHERE amount >= 50 AND id = 6)
union
SELECT id = 6, amount = 50
where (SELECT C = COUNT(*) FROM #test WHERE amount >= 50 AND id = 6) = 0
-- show content of test-table
select * from #test
-- remove Test-table
drop table #test
首先,我尝试重现该行为,是的,这很奇怪。工会 - think 管理空表案例,瞧,这工作正常。
【讨论】:
再一次,它似乎不适用于 MySQL。 SELECT id = 6, amount = 50 不起作用,MySQL 似乎需要一个“FROM”子句。 :(【参考方案4】:好的,这才是真正的问题。试试这个,使用第二个表(#test2):
-- create a test-table with one entry
SELECT id = 1, amount = 50
into #TEST
-- create a second test-table with one entry
SELECT id = 1, amount = 50
into #TEST2
-- see if statement works when table is not empty
INSERT INTO #test (id, amount)
SELECT id = 6, amount = 50
FROM #test
WHERE NOT EXISTS (SELECT * FROM #test WHERE amount >= 50 AND id = 6)
-- show content of test-table
select * from #test
-- empty the test table
truncate table #test
INSERT INTO #test (id, amount) SELECT 6, 50 WHERE NOT EXISTS (SELECT TOP 1 1 FROM #test WHERE amount >= 50 AND id = 6)
-- try to insert a first dataentry
INSERT INTO #test (id, amount)
SELECT id = 6, amount = 50
FROM #test
WHERE NOT EXISTS (SELECT * FROM #test WHERE amount >= 50 AND id = 6)
union
SELECT id = 6, amount = 50
from #test2
where (SELECT C = COUNT(*) FROM #test) = 0
-- show content of test-table
select * from #test
-- remove Test-table
drop table #test
(假设您知道前面有 # 的表,这是 MS-SQL 中的临时表)。
BonyT 已经解释了原因。
【讨论】:
在 MYSQL 下试过这个:INSERT INTO test (id, amount) SELECT id = 6, amount = 50 FROM test WHERE NOT EXISTS (SELECT * FROM test WHERE amount >= 50 AND id = 6) UNION SELECT id = 6, amount = 50 FROM test2 WHERE (SELECT COUNT(*) AS C FROM test) = 0 还是同样的问题?以上是关于带有 INSERT 和 WHERE NOT EXISTS 的奇怪 SQL 行为的主要内容,如果未能解决你的问题,请参考以下文章
INSERT INTO WITH SELECT 和 WHERE(问题)
insert into 和 where not exists
MS-Access:SQL JOIN 和 INSERT INTO 与 WHERE 慢