我的UPDATE语句如下:
UPDATE customer
SET forenames=ot.forenames,
surname =
CASE WHEN ot.safeplace IS NULL
THEN 'test SAFEPLACE IS NULL'
ELSE 'test Safeplace IS NOT NULL'
END,
middlename =
CASE WHEN ot.safeplace IS NULL
THEN 'test2 SAFEPLACE IS NULL'
ELSE 'test2 Safeplace IS NOT NULL'
END,
FROM order_transaction ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
AND customer.custid = 1234
以上作品。它基本上检查另一个表中的字段是否为NULL,然后相应地更新客户的“姓”和“中间名”。如您所见,我重复了两次相同的CASE语句。我的问题是 - 有一种方法可以只指定一次CASE语句吗?
关键是,如果我想根据某种情况更新10个字段,我是否需要包含10个类似的CASE条件?或者可以改进SQL以在WHEN / ELSE子句中只有一个CASE和10个字段更新?
(我使用的是Postgresql 8.2数据库,但我相信上面是标准的SQL)。
非常感谢, 仙人
答案 0 :(得分:8)
我相信以上是标准的SQL
实际上,事实并非如此。标准SQL没有UPDATE..FROM
语法。相反,您需要为每个SET
子句使用标量子查询加上EXISTS
的另一个,因此标准语法甚至更重复,例如
UPDATE customer
SET forenames = (
SELECT ot.forenames
FROM order_transaction AS ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
),
surname = (
SELECT CASE
WHEN ot.safeplace IS NULL
THEN 'test SAFEPLACE IS NULL'
ELSE 'test Safeplace IS NOT NULL'
END
FROM order_transaction AS ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
),
middlename = (
SELECT CASE
WHEN ot.safeplace IS NULL
THEN 'test SAFEPLACE IS NULL'
ELSE 'test Safeplace IS NOT NULL'
END
FROM order_transaction AS ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
)
WHERE customer.custid = 1234
AND EXISTS (
SELECT *
FROM order_transaction AS ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
);
虽然语法看起来很重复,但优秀的优化器应该能够识别重复并相应地进行优化。当前版本的SQL产品是否真的能够在实践中很好地优化它当然是另一回事。但请考虑一下:如果您选择的SQL产品支持标准语法但实际上没有正确优化它,那么“支持”是否值得?
如果您希望使用标准SQL(因为您确实应该使用IMO :)并想要更“紧凑”的语法,那么请查看MERGE
或MERGE (SQL),例如:可能看起来更像这样:
MERGE INTO customer
USING (
SELECT ot.custid, ot.forenames,
CASE
WHEN ot.safeplace IS NULL
THEN 'test SAFEPLACE IS NULL'
ELSE 'test Safeplace IS NOT NULL'
END
FROM order_transaction AS ot
WHERE ot.trans_orderid = 5678
) AS source (custid, forenames, safeplace_narrative)
ON customer.custid = source.custid
AND customer.custid = 1234
WHEN MATCHED THEN
UPDATE
SET forenames = source.forenames,
surname = source.safeplace_narrative,
middlename = source.safeplace_narrative;
答案 1 :(得分:3)
如果要在同一查询级别上执行CASE,则需要重复CASE,就像在group by子句中重复计算列一样。
您的示例查询根本没有显示您想要做什么,您是否真的将所有记录更新为相同的值(固定文本),以及所有每条记录的列。如果您更新以使问题更具相关性,则可能有更好的答案。
<小时/> 但就目前而言,对于您的特定查询,您可以使用类似的内容
UPDATE customer
SET forenames=ot.forenames,
surname = fixedText,
middlename = fixedText
FROM (select o.*, CASE
WHEN safeplace IS NULL
THEN 'test2 SAFEPLACE IS NULL'
ELSE 'test2 Safeplace IS NOT NULL'
END fixedText
from order_transaction o) ot
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
AND customer.custid = 1234
答案 2 :(得分:0)
如果您需要更多次复制确切的案例(多于2个),您可以使用下一个查询。但是你必须真的需要复制案例,而不是使用test和test2(这不是完全相同的情况)。显然,如果您需要将测试/测试2等文本连接到结果,那么您可以在select语句中执行此操作。例如:surname ='test'+ st.result所以有一些可能做一些'黑客'。
UPDATE customer
SET forenames=ot.forenames,
surname = st.result,
middlename = st.result
FROM order_transaction ot
JOIN (select 1 as ID,'test SAFEPLACE IS NULL' as result
union
select 2,'test SAFEPLACE IS NULL') st on case when ot.safeplace is null then 1 else 2 end = st.id
WHERE customer.custid = ot.custid
AND ot.trans_orderid = 5678
AND customer.custid = 1234