【问题标题】:Repeat a command while true or x times (equivalent of while/for loop)重复一个命令 while true 或 x 次(相当于 while/for 循环)
【发布时间】:2019-05-28 11:44:42
【问题描述】:

只要note 字段中仍有sometext,我想重复此命令的次数(表itemNotes 中的几行可能在sometext 字段sometext 中有一个或多个sometext) :

UPDATE itemNotes  
SET 
  note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
WHERE 
  INSTR(LOWER(note), 'sometext') >= 0;

所以一个原型代码是:

While (SELECT * FROM itemNotes  WHERE note like "%sometext%") >1

    UPDATE itemNotes  
    SET 
      note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
    WHERE 
      INSTR(LOWER(note), 'sometext') >= 0;
END

但显然Sqlite3 不支持 While 循环或 for 循环。它们可以用this 之类的东西来模拟,但我很难将我想要的东西与这个查询结合起来:

    WITH b(x,y) AS 
    (
        SELECT 1,2 
        UNION ALL 
        SELECT x+ 1, y + 1 

    FROM b 
    WHERE x < 20
) SELECT * FROM b;

知道怎么做吗?

PS:我不使用replace,因为我想替换sometext的所有大小写组合(例如sometextSOMEtextSOmeText...)参见question


当前输入和期望输出:

对于单行,注释字段可能看起来像(表中的许多行itemNotes可能看起来像这样):

There is SOmetext and also somETExt and more SOMETEXT and even more sometext

查询应该输出:

There is abc and also abc and more abc and even more abc

我在由this 文件(第 85 行)创建的 zotero.sqlite 上执行此操作。该表是由该查询创建的

CREATE TABLE itemNotes (
    itemID INTEGER PRIMARY KEY,
    parentItemID INT,
    note TEXT,
    title TEXT,
    FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
    FOREIGN KEY (parentItemID) REFERENCES items(itemID) ON DELETE CASCADE
);

【问题讨论】:

  • 为什么不用内置的 REPLACE 功能呢?
  • 对不起我没有提到这个:因为我想匹配sometext的所有大小写组合@ cf stackoverflow.com/a/56243026/3154274
  • @CaiusJard,我试过这个UPDATE itemNotes SET note = REPLACE(note , 'sometext', 'abc') COLLATE NOCASE;,但这个查询只替换了sometext的小写。

标签: sqlite


【解决方案1】:

您只需在查询中得到答案:

UPDATE itemNotes  
SET 
  note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
WHERE 
  note LIKE "%sometext%";

它将更新note字段中包含sometext的所有行

更新

如果您想更新在不同情况下多次出现的字段并保留其余文本,最简单的解决方案是使用regex,为此您需要extension

UPDATE itemNotes  
SET 
  note = regex_replace('\bsometext\b',note,'abc')
WHERE 
  note LIKE "%sometext%";

【讨论】:

  • 感谢您,但您的查询仅替换每行中的第一个实例。但是,我在每一行中有很多 sometext
  • @MagTun 你的意思是sometextnote 字段中多次出现?
  • @MagTun 如果您添加示例将很有帮助:输入和期望输出
  • 是的。可以肯定的是,在 itemNotes 表中,我可以有 100 行,每行在 note 字段中都有 50+ sometext
  • @MagTun 我的建议是,如果您无法使扩展工作,只需使用任何脚本语言进行替换,例如:php、python、bash 等
【解决方案2】:

按照 Stephan 在上一条评论中的建议,我使用 python 来执行此操作。

这是我的代码:

import sqlite3
import re
keyword = "sometext"
replacement = "abc"

db = sqlite3.connect(path_to_sqlite)
cursor = db.cursor()

cursor.execute(f'SELECT * FROM itemNotes  WHERE note like "%{keyword}%"')

for row in cursor.fetchall():
    row_regex = re.compile(re.escape(keyword), re.IGNORECASE)
    row_regex_replaced = row_regex.sub(replacement, row[2])

    rowID = row[0]
    sql = "REPLACE INTO itemNotes (itemID,note) VALUES (?,?)"
    data = (rowID, row_regex_replaced)
    cursor.execute(sql, data)
    db.commit()

【讨论】:

    猜你喜欢
    • 2013-07-12
    • 2012-12-13
    • 2016-09-07
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    相关资源
    最近更新 更多