我有以下查询,它通过C#在单个字符串中执行。
SET @out_param := '';
SELECT
sightinguid
FROM
pc
INNER JOIN
c ON uid = id
WHERE
//... other conditions
AND (@out_param:=CONCAT_WS(',', sightinguid, @out_param))
LIMIT 50 FOR UPDATE;
UPDATE pc
SET
last_accessed_timestamp = NOW()
WHERE
sightinguid IN (@out_param);
SELECT @out_param;
我基本上试图将第一个查询的前50个值放在逗号分隔的字符串中,并在结尾处返回此字符串。在这样做之前,我希望update语句在那些相同的记录上执行。但是,只有第一个瞄准者正在更新。当我对sightinguid IN (@out_param)
部分中的多个值进行硬编码时,它会工作并全部更新 - 所以我假设该部分有问题。
由于SELECT
部分,我不能将LIMIT 50
放在子查询中并从那里更新,因为MySQL不允许在子查询中放置LIMIT。
有什么想法吗?
答案 0 :(得分:1)
正如你所说,我不知道你是否可以像这样使用IN
,即使用变量。
无论如何,一个简单的解决方法是使用临时表来存储两个查询之间的信息:
CREATE TEMPORARY TABLE temp(
sightinguid #typeofsightinguid
)
INSERT INTO temp
SELECT //select1
sightinguid
FROM
pc
INNER JOIN
c ON uid = id
WHERE
//... other conditions
AND (@out_param:=CONCAT_WS(',', sightinguid, @out_param))
LIMIT 50 FOR UPDATE;
UPDATE pc
SET
last_accessed_timestamp = NOW()
WHERE
sightinguid IN (SELECT sightinguid FROM temp);
DROP TABLE temp;
SELECT @out_param;
如果临时表不是一个选项(无论什么原因),那么你将不得不做一些像建议的here或here这样的事情:基本上,限制子查询的子查询。像:
UPDATE pc
SET
last_accessed_timestamp = NOW()
WHERE
sightinguid IN (
SELECT sightinguid FROM (
SELECT //select2
sightinguid
FROM pc
INNER JOIN c
ON uid = id
WHERE //... other conditions
LIMIT 50
) tmp
)
另外,还有一件事需要注意,我之前忘记提及:使用LIMIT
而不使用ORDER BY
会导致非确定性查询,即具有不同的行顺序。因此,按照我写的示例,您 COULD 在select1
和select2
上获得2个不同的结果集。