Повторить команду, пока она истинна или x раз (эквивалентно циклу while/for)

Я хотел бы повторить эту команду столько раз, сколько еще осталось 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
);

Почему бы вам не использовать встроенную функцию REPLACE?

Caius Jard 28.05.2019 13:46

Извините, я не упомянул об этом: это потому, что я хочу сопоставить все комбинации регистров sometext cf stackoverflow.com/a/56243026/3154274

MagTun 28.05.2019 13:50

@CaiusJard, я пробовал это UPDATE itemNotes SET note = REPLACE(note , 'sometext', 'abc') COLLATE NOCASE;, но этот запрос заменяет только строчные буквы некоторого текста.

MagTun 28.05.2019 14:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
112
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

У вас просто есть ответ в вашем запросе:

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 28.05.2019 14:16

@MagTun, вы имеете в виду, что у вас есть несколько вхождений sometext в поле note?

Stephan 28.05.2019 14:20

@MagTun будет полезно, если вы добавите и пример: ввод и желаемый вывод

Stephan 28.05.2019 14:21

да. Чтобы быть уверенным, в таблице itemNotes у меня может быть 100 строк, каждая из которых имеет 50+ sometext в поле note.

MagTun 28.05.2019 14:21

Стефан, я добавил пример ввода и вывода в свой вопрос. Извините, что не был точен с самого начала

MagTun 28.05.2019 14:37

@MagTun мой совет: если вы не можете заставить расширение работать, просто замените его на любом языке сценариев, таком как: php, python, bash и т. д.

Stephan 28.05.2019 14:58

Спасибо, Стефан, но почему такую ​​базовую функцию так сложно (или, как вы подразумеваете, невозможно) реализовать в Sqlite3?

MagTun 28.05.2019 15:01

@MagTun, ну, это простой sqllite, это легкая база данных, используемая для простых вещей, поэтому имеет смысл не иметь таких дополнительных функций, как эта, если они вам нужны, тогда просто используйте mysql :), в который встроена функция замены регулярных выражений.

Stephan 28.05.2019 15:25

Как рекомендовал Стефан в своем последнем комментарии, я использовал для этого 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()

Другие вопросы по теме