Я хотел бы повторить эту команду столько раз, сколько еще осталось sometext
в поле note
(несколько строк из таблицы itemNotes
могли иметь один или несколько sometext
в поле note
):
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. Их можно эмулировать с помощью чего-то вроде это, но мне трудно интегрировать то, что я хочу, с этим запросом:
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
(например, sometext
, SOMEtext
, SOmeText
...), см. этот вопрос
Текущий вход и желаемый выход:
Для одной строки поле заметки может выглядеть так (и многие строки в таблице 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
Я делаю это на zotero.sqlite, созданном файлом это (строка 85). Таблица создается этим запросом
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
);
Извините, я не упомянул об этом: это потому, что я хочу сопоставить все комбинации регистров sometext
cf stackoverflow.com/a/56243026/3154274
@CaiusJard, я пробовал это UPDATE itemNotes SET note = REPLACE(note , 'sometext', 'abc') COLLATE NOCASE;
, но этот запрос заменяет только строчные буквы некоторого текста.
У вас просто есть ответ в вашем запросе:
UPDATE itemNotes
SET
note = SUBSTR(note, 0, INSTR(LOWER(note), 'sometext')) || 'abc' || SUBSTR(note, INSTR(LOWER(note), 'sometext')+sometext_len)
WHERE
note LIKE "%sometext%";
Он обновит все строки, содержащие sometext
в поле note
.
ОБНОВИТЬ
Если вы хотите обновить поле, которое имеет несколько вхождений в разных случаях, и сохранить остальную часть текста, самым простым решением imo является использование regex
, и для этого вам нужен расширение
UPDATE itemNotes
SET
note = regex_replace('\bsometext\b',note,'abc')
WHERE
note LIKE "%sometext%";
Спасибо за это, но ваш запрос заменяет только первый экземпляр в каждой строке. Однако у меня много sometext
в каждом ряду.
@MagTun, вы имеете в виду, что у вас есть несколько вхождений sometext
в поле note
?
@MagTun будет полезно, если вы добавите и пример: ввод и желаемый вывод
да. Чтобы быть уверенным, в таблице itemNotes
у меня может быть 100 строк, каждая из которых имеет 50+ sometext
в поле note
.
Стефан, я добавил пример ввода и вывода в свой вопрос. Извините, что не был точен с самого начала
@MagTun мой совет: если вы не можете заставить расширение работать, просто замените его на любом языке сценариев, таком как: php, python, bash и т. д.
Спасибо, Стефан, но почему такую базовую функцию так сложно (или, как вы подразумеваете, невозможно) реализовать в Sqlite3?
@MagTun, ну, это простой sqllite, это легкая база данных, используемая для простых вещей, поэтому имеет смысл не иметь таких дополнительных функций, как эта, если они вам нужны, тогда просто используйте mysql :), в который встроена функция замены регулярных выражений.
Как рекомендовал Стефан в своем последнем комментарии, я использовал для этого 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()
Почему бы вам не использовать встроенную функцию REPLACE?