SQLite:插入或替换某些列,不要用 NULL 覆盖其他列?

问题描述 投票:0回答:4

想象我有一张桌子(冰箱),上面有列:(日期(PK)、水果、蔬菜、淀粉、糖果)。这是一个示例行:

date     | fruits | veggies | starches | sweets 
20180220 | melon  | potato  |  pasta   | fudge

我只想用以下内容插入或替换冰箱中的某些列:

> INSERT or REPLACE into refrigerator (date, fruits, veggies, starches) VALUES ("20180220", "apple", "carrot", "bread")

当我这样做时,如果我没有为 (sweets) 指定值,它将被 NULL 覆盖。

date     | fruits | veggies | starches | sweets 
20180220 | apple  | carrot  |  bread   | NULL

不替换我指定的值的正确方法是什么?

我确信这是显而易见的事情。随意嘲笑我吧。

sql sqlite
4个回答
8
投票

现在它按预期工作,并且如果该行不存在也会插入该行。 如果没有 UNION ALL,它将无法正常工作。第一个 SELECT 使用 COALESCE() 在行确实存在的情况下保留现有列值。第二个带有 NOT EXISTS 的 SELECT 涵盖了该行不存在的情况,因此它构造了一个。因此,UNION ALL 只返回 1 行:来自现有行的“合并”行,或全新的行。然后,REPLACE INTO 通过主键将此合并/创建的行替换回表中。

CREATE TABLE refrigerator
  (
  date TEXT(8) NOT NULL PRIMARY KEY
  , fruits TEXT(50) NULL
  , veggies TEXT(50) NULL
  , starches TEXT(50) NULL
  , sweets TEXT(50) NULL
  );

INSERT INTO refrigerator (date, fruits, veggies, starches, sweets)
VALUES ("20180220", "melon", "potato", "pasta", "fudge");

REPLACE INTO refrigerator (date, fruits, veggies, starches, sweets)
SELECT
  date
  , COALESCE("apple", fruits) as fruits
  , COALESCE("carrot", veggies) as veggies
  , COALESCE("bread", starches) as starches
  , COALESCE(NULL, sweets) as sweets
 FROM
   refrigerator
 WHERE
   date = "20180220"
UNION ALL
SELECT
  T.date, T.fruits, T.veggies, T.starches, T.sweets
FROM
(
SELECT
  "20180220" as date
  , "apple" as fruits
  , "carrot" as veggies
  , "bread" as starches
  , NULL as sweets
) AS T
WHERE
  NOT EXISTS (SELECT * FROM refrigerator AS R WHERE R.date = T.date);

SELECT date, fruits, veggies, starches, sweets FROM refrigerator;

这是一个 SQL Fiddle:冰箱 SQL Fiddle


7
投票

我用两行解决了这个问题。

UPDATE refrigerator SET fruits='apple', veggies='carrot', starches='bread' WHERE date='20180220';

然后

INSERT or IGNORE INTO refrigerator (fruits, veggies, starches) VALUES ("apple", "carrot", "bread");

我在逆向思考问题,这可能使这里的答案过于复杂。如果存在带有(日期)的行,我首先更新特定列。如果不存在,下一行将插入包含所需信息的新行 - 如果存在则忽略它。

这种方式可能会出现任何并发症吗?我已经测试过了,到目前为止一切都按预期工作。


0
投票

要更新现有数据,请使用更新

https://www.tutorialspoint.com/sqlite/sqlite_update_query.htm

将水果列更新为苹果使用的示例

更新冰箱套装水果 = 'Apple',其中 YOURWHERECLAUSEHERE

至于如果你什么都不提供的话,插入什么是期望插入的?该程序不会读懂你的想法。


0
投票

提出问题时,SQLite 中尚不提供此功能。

我使用 UPSERT 解决了这个问题 (https://sqlite.org/lang_upsert.html)。

INSERT INTO refrigerator (date, fruits, veggies, starches) VALUES ("20180220", "apple", "carrot", "bread")
 ON CONFLICT(date) DO UPDATE SET fruits="apple", veggies="carrot", starches="bread";

这会尝试将数据插入数据库,当由于唯一性约束而发生冲突时,它会执行更新;因此现有数据保持不变,仅更改指定的列。

© www.soinside.com 2019 - 2024. All rights reserved.