Как создать триггер SQLite для автоматического расчета столбцов после INSERT?

Этот вопрос является продолжением моего предыдущего вопроса, на который у меня есть рабочий ответ:

но теперь мне нужно сделать то же самое в SQLite. Я прочитал этот вопрос:

но мне не хватает подробностей, чтобы использовать их, отсюда и этот более подробный вопрос.

Учитывая эту таблицу:

CREATE TABLE myTable 
(
    datetime TEXT,
    gen_year INT GENERATED ALWAYS AS (SUBSTRING(datetime,7,4)) STORED,
    gen_mon INT GENERATED ALWAYS AS (SUBSTRING(datetime,4,2)) STORED,
    gen_date INT GENERATED ALWAYS AS (SUBSTRING(datetime,1,2)) STORED,
    gen_hr INT GENERATED ALWAYS AS (SUBSTRING(datetime,12,2)) STORED,
    gen_min INT GENERATED ALWAYS AS (SUBSTRING(datetime,15,2)) STORED,
    gen_sec INT GENERATED ALWAYS AS (SUBSTRING(datetime,18,2)) STORED,
    gen_ms INT GENERATED ALWAYS AS (SUBSTRING(datetime,21,3)) STORED,
    gen_isodate TEXT GENERATED ALWAYS AS (
        FORMAT("%04d",gen_year) || "-" ||
        FORMAT("%02d",gen_mon) || "-" ||
        FORMAT("%02d",gen_date) || " " ||
        FORMAT("%02d",gen_hr) || ":" ||
        FORMAT("%02d",gen_min) || ":" ||
        FORMAT("%02d",gen_sec) || "." ||
        FORMAT("%03d",gen_ms)
    ) STORED,
    sys_id INT,
    cputil REAL,
    memfree REAL,
    sessnum INT,
    util_lag REAL,   -- meant to be filled by TRIGGER upon/after INSERT
    mem_lag REAL,    -- meant to be filled by TRIGGER upon/after INSERT
    util_diff REAL,  -- meant to be filled by TRIGGER upon/after INSERT
    mem_diff REAL,   -- meant to be filled by TRIGGER upon/after INSERT
    util_change TEXT -- meant to be filled by TRIGGER upon/after INSERT
);

Я пытаюсь использовать триггер для вычисления различий в столбцах cputil и memfree между строками и добавлять строку ТЕКСТ в столбец util_change, все на INSERT для каждой новой строки.

У меня есть следующий триггер, который принимается (т.е. не выдает ошибок), созданный с помощью ChatGPT:

-- chatGPT v1 with updates
CREATE TRIGGER tr_fill_calculated_columns
    AFTER INSERT ON myTable
BEGIN
    UPDATE myTable
    SET util_lag = (SELECT LAG(cputil) OVER (ORDER BY gen_isodate ASC) FROM myTable WHERE datetime = NEW.datetime),
        mem_lag = (SELECT LAG(memfree) OVER (ORDER BY gen_isodate ASC) FROM myTable WHERE datetime = NEW.datetime),
        util_diff = NEW.cputil - NEW.util_lag,
        mem_diff = NEW.freemem - NEW.mem_lag
    WHERE datetime = NEW.datetime;
END;

но проблема в том, что он просто не работает - триггер не может вычислить нужные мне столбцы. Когда я делаю INSERT со следующими данными:

INSERT INTO myTable (datetime,sys_id,cputil,memfree,sessnum) 
VALUES
 ("06.03.2021 23:10:49.057",100,0.5,0.9,97)
,("24.03.2021 17:04:20.715",100,0.28,0.19,167)
,("09.06.2021 10:24:09.880",100,0.59,0.25,138)
,("30.06.2021 12:41:38.694",100,0.34,0.49,102)
,("28.07.2021 23:12:40.555",100,0.84,0.03,95)
,("22.10.2021 03:55:31.215",100,0.44,0.04,56)
,("25.08.2022 11:11:01.672",100,0.7,0.58,120)
,("25.08.2022 11:11:02.119",100,0.97,0.18,155)
,("25.08.2022 11:11:03.893",100,0.68,0.16,123)
,("25.08.2022 11:11:04.390",100,0.25,0.67,167)
,("25.08.2022 11:11:05.538",100,0.48,0.4,169)
,("25.08.2022 11:11:06.204",100,0.96,0.47,180)
,("25.08.2022 11:11:07.070",100,0.94,0.07,95)
,("25.08.2022 11:11:08.845",100,0.5,0.48,132)
,("25.08.2022 11:11:09.919",100,0.02,0.07,154)
,("25.08.2022 11:11:10.280",100,0.41,0.05,64)
,("25.08.2022 11:11:11.100",100,0.68,0.77,88)
,("25.08.2022 11:11:12.687",100,0.81,0.05,57)
,("25.08.2022 11:11:13.707",100,0.25,0.71,159)
,("25.08.2022 11:11:14.922",100,0.23,0.58,193)
,("25.08.2022 11:11:15.836",100,0.87,0.32,158)
,("25.08.2022 11:11:16.695",100,0.53,0.46,177)
,("25.08.2022 11:11:17.576",100,0.77,0.46,188)
,("25.08.2022 11:11:18.932",100,0.45,0.47,56)
,("25.08.2022 11:11:19.638",100,0.87,0.41,184)
,("25.08.2022 11:11:20.489",100,0.55,0.05,54)
,("25.08.2022 11:11:21.404",100,0.31,0.02,72)
,("25.08.2022 11:11:22.704",100,0.78,0.52,152)
,("25.08.2022 11:11:23.166",100,0.12,0.34,119)
,("25.08.2022 11:11:24.067",100,0.98,0.68,102)
,("25.08.2022 11:11:25.423",100,0.85,0.81,136)
,("25.08.2022 11:11:26.544",100,0.91,0,169)
,("25.08.2022 11:11:27.835",100,0.82,0.95,186)
,("25.08.2022 11:11:28.055",100,0.53,0.35,50)
,("25.08.2022 11:11:29.769",100,0.39,0.79,144)
,("25.08.2022 11:11:30.935",100,0.39,0.15,180)
,("25.08.2022 11:11:31.153",100,0.76,0.26,116)
,("25.08.2022 11:11:32.305",100,0.76,0.06,175)
,("25.08.2022 11:11:33.392",100,0.91,0.98,173)
,("25.08.2022 11:11:34.458",100,0.39,0.18,111)
,("25.08.2022 11:11:35.227",100,0.73,0.31,75)
,("25.08.2022 11:11:36.584",100,0.8,0.58,56)
,("25.08.2022 11:11:37.619",100,0.11,0.84,51)
,("25.08.2022 11:11:38.407",100,0.67,0.85,166)
,("25.08.2022 11:11:39.070",100,0.28,0.31,159)
,("25.08.2022 11:11:40.674",100,0.05,0.38,176)
,("25.08.2022 11:11:41.422",100,0.87,0.47,110)
,("25.08.2022 11:11:42.235",100,0.64,0.97,194)
,("25.08.2022 11:11:43.780",100,0.07,0.36,63)
,("25.08.2022 11:11:44.903",100,0.5,0.17,89)
RETURNING *;

SELECT * FROM myTable;

util_lag, mem_lag, util_diff и mem_diff — все [NULL] для всех строк, а не только для первой (ожидаемой).

Пример вывода:

Я также попытался добавить последние четыре строки расчета в триггер столбца util_change следующим образом:

DROP TRIGGER tr_fill_calculated_columns;

CREATE TRIGGER tr_fill_calculated_columns
    AFTER INSERT ON myTable
BEGIN
    UPDATE myTable
    SET util_lag = (SELECT LAG(cputil) OVER (ORDER BY gen_isodate ASC) FROM myTable WHERE datetime = NEW.datetime),
        mem_lag = (SELECT LAG(memfree) OVER (ORDER BY gen_isodate ASC) FROM myTable WHERE datetime = NEW.datetime),
        util_diff = NEW.cputil - NEW.util_lag,
        mem_diff = NEW.memfree - NEW.mem_lag
        util_change = (CASE
            WHEN NEW.util_diff > 0 THEN 'Up'
            WHEN NEW.util_diff < 0 THEN 'Down'
            ELSE '')
    WHERE datetime = NEW.datetime;
END;

но это не удалось с ошибкой:

Ошибка SQL [2]: [SQLITE_ERROR] Ошибка SQL или отсутствующая база данных (рядом с «util_change»: синтаксическая ошибка)

Я попытался заставить ChatGPT помочь мне добавить окончательный вычисляемый столбец util_change, и он выдал следующее:

-- Create a trigger that fires after inserting a new row into my_table
CREATE TRIGGER tr_fill_calculated_columns
AFTER INSERT ON myTable
BEGIN
    -- Declare variables to store the previous row's values
    DECLARE prev_cputil REAL;
    DECLARE prev_freemem REAL;
    DECLARE util_diff REAL;
    DECLARE mem_diff REAL;
    DECLARE util_change TEXT;

    -- Get the previous row's values for cputil and freemem
    SELECT cputil, freemem
    INTO prev_cputil, prev_freemem
    FROM myTable
    WHERE datetime = (SELECT MAX(datetime) FROM myTable);

    -- Calculate the differences
    SET util_diff = NEW.cputil - prev_cputil;
    SET mem_diff = NEW.freemem - prev_freemem;

    -- Determine the value for util_change
    IF util_diff > 0 THEN
        SET util_change = 'Up';
    ELSEIF util_diff < 0 THEN
        SET util_change = 'Down';
    ELSE
        SET util_change = '';
    END IF;

    -- Update the inserted row with calculated values
    UPDATE myTable
    SET util_lag = prev_cputil,
        mem_lag = prev_freemem,
        util_diff = util_diff,
        mem_diff = mem_diff,
        util_change = util_change
    WHERE datetime = NEW.datetime;
END;

но это также просто терпит неудачу из-за синтаксической ошибки:

Ошибка SQL [2]: [SQLITE_ERROR] Ошибка SQL или отсутствующая база данных (рядом с «DECLARE»: синтаксическая ошибка)

Может ли кто-нибудь внести исправления в мой код триггера SQLite там, где это необходимо?

Зачем вам триггеры? Сгенерированные столбцы (которые вы уже используете в датах) должны выполнять то, что вы хотите, например, вычисления mem*.

TheNomad 16.03.2024 09:39

В случае, если это не очевидно из названий полей util_lag, mem_lag, мне нужно получить значения из предыдущей строки, что, насколько я знаю, невозможно сделать без ТРИГГЕРА. Наверное, мне следовало назвать их prev_util и prev_mem - извините за это . Если вы не знаете способа получить значение из предыдущей строки, которого нет у других, мне говорят, что необходим ТРИГГЕР.

skeetastax 16.03.2024 09:51

Что касается ошибки SQL [2]: [SQLITE_ERROR] Ошибка SQL или отсутствующая база данных (рядом с «util_change»: синтаксическая ошибка), я считаю, что в вашем CASE отсутствует END. Перед util_change также отсутствует запятая. Что касается примера ChatGPT, я думаю, он показал вам процедуру, и вы переместили ее в триггер, верно? AFAIK, Sqlite не позволяет DECLARE, за исключением процедур (но я признаю, что прошло некоторое время с тех пор, как я прикоснулся к Sqlite).

TheNomad 16.03.2024 18:39

Второй пример ChatGPT является дословным. У меня нет навыков конвертировать ПРОЦЕДУРУ в ТРИГГЕР. Единственные изменения, которые я внес в пример ChatGPT v1, — это добавление функции LAG(), поскольку я считал, что ее следует использовать. Я не мог понять, как исходный пример получал значения из предыдущей строки, что и необходимо для расчета «разницы».

skeetastax 18.03.2024 00:26
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
4
111
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете перенаправлять и изменять вставки в представлении из триггера вместо : демо.

Строка начальной загрузки упростит триггер:

insert into myTable(datetime)
select '-infinity';

Без него триггеру пришлось бы всегда учитывать два случая:

  • если строк нет, вставьте входящую строку, не изменяя ее.
  • если есть строки, вычислите относительные значения _lag и _diff

Добавляя начальную строку заранее, вам не нужно учитывать первый случай.

CREATE INDEX dtidx ON myTable (datetime);
CREATE VIEW v_myTable AS SELECT * FROM myTable;
CREATE TRIGGER cust_addr_chng
INSTEAD OF INSERT ON v_myTable 
BEGIN
  INSERT INTO myTable
  SELECT NEW.datetime,
         NEW.sys_id,
         NEW.cputil,
         NEW.memfree,
         NEW.sessnum,
         previous.cputil,--util_lag
         previous.memfree,--mem_lag
         NEW.cputil-previous.cputil,--util_diff 
         NEW.memfree-previous.memfree,--mem_diff
         CASE WHEN NEW.cputil-previous.cputil > 0
              THEN 'Up'
              WHEN NEW.cputil-previous.cputil < 0
              THEN 'Down'
              WHEN NEW.cputil-previous.cputil = 0
              THEN ''
         END --util_change
  FROM myTable AS previous
  ORDER BY datetime DESC
  LIMIT 1;
END;
дата и время sys_id процессор мемфри сесснум util_lag mem_lag util_diff mem_diff util_change -бесконечность нулевой нулевой нулевой нулевой нулевой нулевой нулевой нулевой нулевой 2019/05/03 08:06:14 100 0,57 0,51 47 нулевой нулевой нулевой нулевой нулевой 2019/05/03 08:11:14 100 0,47 0,62 43 0,57 0,51 -0,099999999999999998 0,109999999999999999 Вниз 2019/05/03 08:16:14 100 0,56 0,57 62 0,47 0,62 0.09000000000000008 -0,0500000000000000044 Вверх 2019/05/03 08:21:14 100 0,57 0,56 50 0,56 0,57 0,0099999999999999898 -0,0099999999999999898 Вверх 2019/05/03 08:26:14 100 0,35 0,46 43 0,57 0,56 -0,219999999999999997 -0,10000000000000003 Вниз 2019/05/03 08:31:14 100 0,41 0,58 48 0,35 0,46 0,06 0,11999999999999994 Вверх

Я никогда раньше не слышал термина «начальный ряд». Кажется, я это понимаю, но не уверен. В любом случае я надеюсь избежать создания представления, поскольку, если оно не материализовано, я понимаю, что представление является лишь временным, т. е. находится в памяти. Если/когда машина будет перезагружена, я не хочу, чтобы все эти рассчитанные значения столбцов были потеряны, они должны были быть постоянными. Опять же, мы говорим о сотнях миллионов строк (первоначальные вычисления будут медленными, но расчеты обслуживания по мере добавления новых строк должны быть очень быстрыми).

skeetastax 18.03.2024 01:25

Я только что заметил, что вы ОГРАНИЧИВАЕТЕ просмотр последней строкой. Поправьте меня, если я ошибаюсь: он создает представление в качестве заполнителя только для вставляемой строки, рассчитывает значения для строки представления, а затем записывает строку представления в реальную таблицу?

skeetastax 18.03.2024 01:29

Я не знаю почему, но с помощью этого решения я получаю [NULL] для всех вычисляемых столбцов. Мне интересно, есть ли проблемы с DBeaver, инструментом, который я использую. Возможно, в DBeaver есть ошибка... как вы думаете?

skeetastax 18.03.2024 11:08

Я бы не беспокоился о том, что он останется в памяти или потеряется при перезагрузке. Из документа: «Команда CREATE VIEW присваивает имя предварительно упакованному оператору SELECT» - большинство СУБД делают это именно так. Он занимает нулевое пространство, а выборка из представления в значительной степени преобразуется в выборку из подзапроса, содержащего его определение. Триггер в представлении просто перенаправляет операторы insert, чтобы сохранить входящие строки в базовой таблице — они сохраняются в ней так же, как если бы вы вставили их напрямую.

Zegarek 18.03.2024 12:54

Определение представления на самом деле не имеет значения: представление используется здесь просто как точка, с помощью которой вы перехватываете и изменяете вставку на лету, что невозможно для прямых вставок в базовую таблицу. Что касается результатов null для вычисляемых столбцов, я предполагаю, что вы вставили строки непосредственно в таблицу, что не активирует триггер в представлении, или вы проверили строки, вставленные в представление, с помощью предложения returning - и в этом случае вы я увижу их состояние до изменения триггером: демо.

Zegarek 18.03.2024 13:00

Я получил предложение RETURNING * из вашего примера для PostgreSQL здесь: dbfiddle.uk/NQUithQ3. Признаюсь, я не совсем понимаю, что оно делает.

skeetastax 19.03.2024 01:05

"захватить и изменить вставку на лету" - так я понял ВИД.

skeetastax 19.03.2024 01:06

«я предполагаю, что вы вставили строки непосредственно в таблицу, что не активирует триггер в представлении»… ааа… я вижу, что ваш TRIGGER находится в представлении, а не в таблице. Я только что еще раз проверил вашу демонстрацию - я совершенно не заметил, что вы вставляете строки в представление, а не в базовую таблицу. Итак, вы вставляете представление между вашими данными и постоянным хранилищем таблиц как фильтр, верно?

skeetastax 19.03.2024 01:13

Это также было во вступительном заявлении :) Это деталь реализации SQLite, согласно которой вы не можете иначе перехватить операцию — триггер действует как фильтр, но представление — это всего лишь способ получить это instead of trigger. Только представления могут иметь такие

Zegarek 19.03.2024 03:07
Ответ принят как подходящий

В качестве альтернативы триггеру, который изменяет вставку на лету в действии instead of, вы можете изменить строку после факта: демо.

CREATE INDEX dtidx ON myTable (datetime);
CREATE TRIGGER cust_addr_chng
AFTER INSERT ON myTable 
BEGIN
  UPDATE myTable
  SET util_lag    =previous.cputil,
      mem_lag     =previous.memfree,
      util_diff   =NEW.cputil-previous.cputil,
      mem_diff    =NEW.memfree-previous.memfree,
      util_change =CASE WHEN NEW.cputil-previous.cputil > 0
                        THEN 'Up'
                        WHEN NEW.cputil-previous.cputil < 0
                        THEN 'Down'
                        WHEN NEW.cputil-previous.cputil = 0
                        THEN ''
                   END
  FROM (SELECT * FROM myTable
        ORDER BY datetime DESC
        LIMIT 1, 1) AS previous
  WHERE myTable.datetime=NEW.datetime;
END;

В сценарии after новая строка теперь является последней в таблице, поэтому вам нужно LIMIT 1, 1, чтобы получить предпоследнюю строку в качестве ее задержки/предыдущей.

дата и время sys_id процессор мемфри сесснум util_lag mem_lag util_diff mem_diff util_change 2019/05/03 08:06:14 100 0,57 0,51 47 нулевой нулевой нулевой нулевой нулевой 2019/05/03 08:11:14 100 0,47 0,62 43 0,57 0,51 -0,099999999999999998 0,109999999999999999 Вниз 2019/05/03 08:16:14 100 0,56 0,57 62 0,47 0,62 0.09000000000000008 -0,0500000000000000044 Вверх 2019/05/03 08:21:14 100 0,57 0,56 50 0,56 0,57 0,0099999999999999898 -0,0099999999999999898 Вверх 2019/05/03 08:26:14 100 0,35 0,46 43 0,57 0,56 -0,219999999999999997 -0,10000000000000003 Вниз 2019/05/03 08:31:14 100 0,41 0,58 48 0,35 0,46 0,06 0,11999999999999994 Вверх

Мне кажется странным, что функцию LAG() нельзя использовать для того, что я пытаюсь сделать. Мне кажется само собой разумеющимся, что так и должно быть. Вместо этого нам приходится заниматься этими «кодонастиками» :D. Полезно знать дополнительное необязательное поле для предложения LIMIT.

skeetastax 18.03.2024 01:48

Какой из двух ваших ответов, по вашему мнению, будет более эффективным?

skeetastax 18.03.2024 01:51

Я получаю смешанные результаты с этим ответом. Если я вставлю одну строку в один оператор, похоже, что она не получит значений предыдущей строки. Если я вставлю блок строк в один оператор, некоторые строки будут правильно получать значения из предыдущей строки, а другие — нет. Иногда группа строк получает «предыдущие» значения из одной предыдущей строки, поэтому все они одинаковы, что является неверным результатом.

skeetastax 18.03.2024 10:10

29.03.2021 19:49:55.419,2021,3,29,19,49,55,419,2021-03-29 19:49:55.419,100,0.6,0.8,177,,,,,\n 09.06.2021 14 :48:16.628,2021,6,9,14,48,16,628,2021-06-09 14:48:16.628,100,0.67,0.61,143,0.67,0.61,0.0,0.0,\n 22.07.2021 07 :51:11.373,2021,7,22,7,51,11,373,2021-07-22 07:51:11.373,100,0.01,0.1,135,0.01,0.1,0.0,0.0,\n 06.03.2021 23 :10:49.057,2021,3,6,23,10,49,57,2021-03-06 23:10:49.057,100,0.5,0.9,97,0.01,0.1,0.49,0.8,Вверх\n 28.07 .2021 23:12:40.555,2021,7,28,23,12,40,555,2021-07-28 23:12:40.555,100,0.84,0.03,95,0.6,0.8,0.24,-0.77,Вверх

skeetastax 18.03.2024 10:49

Может показаться, что lag() просто означает предыдущую строку, но учтите, что это оконная функция. Это предыдущая строка в окне, которая сужает подмножество того, что выбрано. Вероятно, вы могли бы его применить, но это не будет иметь особого смысла — это полезно, когда у вас есть набор строк и вы хотите каким-то образом соотнести каждую из них со своими предшественниками. Между тем, «SQLite поддерживает только триггеры FOR EACH ROW, а не триггеры FOR EACH STATEMENT», поэтому вы всегда имеете дело только с одной строкой, и вам нужно только определить предшественника этой единственной строки.

Zegarek 18.03.2024 13:09

В предыдущей теме я упоминал, что lag(), вероятно, может творить чудеса с триггером на уровне оператора - для вставки из нескольких строк вы просто получите одну «загрузочную строку», самую последнюю в таблице, которая хронологически предшествует первой в для входящего пакета вы бы отдали его для первой строки, чтобы отключить _diff, а затем использовали lag() для остальной части пакета.

Zegarek 18.03.2024 13:13

Что касается «аномалии», мне нужно посмотреть, что именно вы делаете. Оба моих ответа связаны с демо-версией, и она отлично работает независимо от того, вставляете ли вы несколько одновременно или делаете это один за другим. Вот пример, где я разделяю партию и вставляю ее одну за другой, затем проверяю после каждой вставки, а позже вставляю все остальные сразу: демо. Если вы можете воспроизвести поведение, с которым столкнулись, но сделайте это на db<>fiddle, нажмите run и поделитесь ссылкой на это, я посмотрю. Вы запускаете вставки из приложения, используя пул? Из отдельных вкладок/сессий в DBeaver?

Zegarek 18.03.2024 13:20

Я просто запускаю весь SQL на одной вкладке в DBeaver. Никакого пула, это все есть на этом ноуте (на котором я тоже здесь пишу). Я перепроверил каждую строку своего кода и обнаружил некоторые различия между вашим и моим, поэтому сообщу о своих результатах. Теперь я думаю, что это я делаю неправильно, а не DBeaver или ваш код.

skeetastax 19.03.2024 02:19

Я только что заметил, что некоторые из ваших временных меток имеют другой формат: это может быть причиной. SQLite принимает только ISO-8601 ГГГГ-ММ-ДД ЧЧ:ММ:СС. Если вы используете что-нибудь еще, он тихо предположит, что это просто текст, поэтому вся логика, определяющая, что считать последней строкой, полностью изменится.

Zegarek 19.03.2024 02:54

Да, я вижу, что в SQLite нет внутреннего типа datetime. Вот именно это я и запустил в DBeaver, и это сработало! dbfiddle.uk/ljgXecSu. Как ни странно, <db.fiddle> выдает ошибку. Я добавил в таблицу больше вычисляемых столбцов, чтобы извлечь поля даты и времени из ТЕКСТА и создать правильное сортируемое поле gen_isodate. Исходный формат даты и времени — DD.MM.YYYY HH:mm:ss.sss, а не YYYY-MM-DD HH:mm:ss.sss. Я изменил исходный формат, чтобы упростить свой вопрос, поскольку мое внимание было сосредоточено на расчетах разницы строк.

skeetastax 19.03.2024 03:17

Я также предполагал (возможно, ошибочно, хотя я так не думаю), что SQLite будет сортировать столбец «искусственный» datetime TEXT именно так — TEXT, лексикографически.

skeetastax 19.03.2024 03:21

Вот ваша исправленная рабочий пример: dbfiddle.uk/TGLeFxkD ей не нравились двойные кавычки вместо одинарных кавычек и не нравилось несколько команд в одном блоке.

Zegarek 19.03.2024 03:52

Мне только что пришло в голову: если вы используете оператор SELECT в TRIGGER, можете ли вы использовать там функцию LAG(), и стоит ли оно того?

skeetastax 20.03.2024 01:07

Да, можно, и нет, оно того не стоит, если только SQLite не добавит триггеры на уровне операторов или не изменится логика в вашем приложении.

Zegarek 20.03.2024 07:08

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

Sentry, Sequelizejs: есть ли способ зафиксировать оператор SQL, вызывающий ошибку?
Чтение SQL-таблицы пандами вызывает NotImplementedError
Как загрузить данные таблицы Android.database.sqlite в счетчик? (В таблице есть данные, но она не загружается)
TypeError: именованные параметры можно передавать только внутри простых объектов при попытке обработки ошибок Sqlite с помощью стрелочных функций ES6
Запрос нескольких произвольных тегов в базе данных SQLite в программе Python
SQLite, «SELECT 0 OR NULL» против «SELECT 1 OR NULL», странный результат
Почему Prisma генерирует уникальный индекс вместо ограничения уникальности столбца на основе «уникального» значения в схеме?
Почему EF Core SQLite возвращает неправильное значение int?
Как создать PostgreSQL TRIGGER для автоматического расчета столбцов после INSERT?
Как создать постоянный (СОХРАНЕННЫЙ) Сгенерированный (расчетный/вычисляемый) столбец в SQLIte3 с помощью функции LAG и IF-THEN-ELSE?