Как увеличить поле, если запись уже существует?

У меня есть скрипт bash для вывода файла csv в sqlite3:

 cat <<EOF | sqlite3 "$1.db"
CREATE TABLE IF NOT EXISTS 'dump' (
pk INTEGER PRIMARY KEY,
first TEXT,
last TEXT,
seen INTEGER,
created DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(first, last)
);
.mode csv
.separator ";"
.import '$1.tmp' 'dump'
EOF

Это работает для базового дампа, но этот файл дампа постоянно обновляется, и мне нужно отслеживать, сколько раз видели этого человека. Как я могу увеличить поле «видимо», если этот человек уже есть в базе данных?

Сомневаюсь, что вы сможете сделать это со встроенным .import. Вам следует написать сценарий на языке программирования, который просматривает CSV и выполняет обновление.

Barmar 17.08.2024 00:38

Импортируйте во временную таблицу, а затем обновите таблицу всем, что захотите.

Diego Torres Milano 17.08.2024 00:45

веб-поиск sqlite import csv upsert выдает несколько совпадений, которые говорят об одном и том же (при условии, что вы делаете это через sqlite3 командную строку) ... импортируйте в промежуточную таблицу, а затем insert into основную таблицу select from промежуточную таблицу on duplicate key update ... (например, это)

markp-fuso 17.08.2024 01:12

Какой формат входного файла? Команда .import требует, чтобы файл csv соответствовал схеме таблицы. Это означает, что у вас уже есть поля pk, seen и created в файле .csv. Каков процесс заполнения/обновления этих полей в файле?

White Owl 17.08.2024 02:07
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
4
80
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Шаги сценария.

Шаг 1. Создайте temp таблицу:

CREATE TABLE IF NOT EXISTS temp (…);

Шаг 2. Создайте dump таблицу:

CREATE TABLE IF NOT EXISTS dump (…);

Шаг 3. Откройте транзакцию.

BEGIN TRANSACTION;

Шаг 4. Очистите таблицу:

DELETE FROM temp;

Шаг 5. Импортируйте данные в таблицу temp.

Шаг 6. Объедините данные с помощью Upsert:

INSERT INTO dump (…)
SELECT … FROM temp
ON CONFLICT(first, last) DO UPDATE SET
seen = seen + 1
…

Шаг 7. Зафиксируйте изменения.

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

У вас есть сценарий Bash, который импортирует CSV в базу данных SQLite. CSV постоянно обновляется, и вам необходимо увеличивать поле seen для существующих записей при вставке новых.

Решение: эффективный UPSERT с транзакциями SQLite

Чтобы эффективно справиться с этим, мы будем использовать синтаксис INSERT OR REPLACE SQLite внутри транзакции.

cat <<EOF | sqlite3 "$1.db"
BEGIN TRANSACTION;

CREATE TABLE IF NOT EXISTS 'dump' (
    pk INTEGER PRIMARY KEY,
    first TEXT,
    last TEXT,
    seen INTEGER DEFAULT 1,
    created DATETIME DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(first, last)
);

.mode csv
.separator ";"

-- Create a temporary table with necessary columns
CREATE TEMP TABLE tmp_import (
    first TEXT,
    last TEXT
);

-- Import the CSV into the temporary table
.import '$1.tmp' tmp_import;

-- Efficiently insert or update records
INSERT OR REPLACE INTO dump (first, last, seen)
SELECT first, last, seen + 1
FROM tmp_import;

DROP TABLE tmp_import;
COMMIT;
EOF

Объяснение:

  • Начать транзакцию: обеспечивает согласованность данных, особенно для одновременных обновлений.
  • Создать таблицу: создает таблицу dump, если она не существует.
  • Временная таблица: создает временную таблицу для эффективной обработки.
  • Импортировать CSV: импортирует данные CSV во временную таблицу.
  • UPSERT: использует INSERT OR REPLACE для вставки новых записей или обновления. существующие, увеличивая количество seen.
  • Удалить временную таблицу: очищает временную таблицу.
  • Зафиксировать транзакцию: фиксирует изменения в базе данных.
cat здесь бесполезен. Прямо сделайте sqlite3 "$1.db" <<EOF или sqlite3 "$1.db" <<'SQL', чтобы содержимое вашего документа не расширяло оболочку и было ясно, что это синтаксис SQL.
Léa Gris 17.08.2024 12:31

На основе ответа Md Mahfuz RP с исправленной и проверенной рабочей реализацией.

#!/usr/bin/env sh

sqlite3 "$1.db" <<SQL
CREATE TABLE IF NOT EXISTS 'dump' (
    pk INTEGER PRIMARY KEY,
    first TEXT,
    last TEXT,
    seen INTEGER DEFAULT 0,
    created DATETIME DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(first, last)
);

.mode csv
.separator ";"

-- Create a temporary table in memory with necessary columns
PRAGMA temp_store = 2; -- 2 means use in-memory
DROP TABLE IF EXISTS tmp_import;
CREATE TEMP TABLE tmp_import (
    first TEXT,
    last TEXT
);

-- Import the CSV into the temporary table
.import '$1.csv' tmp_import

-- Efficiently insert or update records as a single transaction
BEGIN TRANSACTION;

-- Imports new lines from tmp_import if they don't exist in dump
INSERT OR IGNORE INTO dump (first, last)
SELECT first, last
FROM tmp_import;

-- Increment the seen of dump's lines that are in tmp_import
UPDATE dump
SET seen = seen + 1
FROM (
  SELECT first, last FROM tmp_import
) AS t
WHERE t.first = dump.first AND t.last = dump.last;

COMMIT;

-- Dispose of the in-memory tmp_import table
DROP TABLE IF EXISTS tmp_import;
SQL

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