Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Как сделать запрет на повтор?

#sqlite


Проблема такая, если занесли запись через запрос 'INSERT INTO' в таблицу, и второй
раз допустим случайно с таким же названиям, то данные не добавляются и это хорошо,
НО сам 'id' увеличивается в значении, каждой раз на одиницю, если совпадают названия
, что в моем случаи мне не подходит , возможно ли как-то это решить ?

Параметры таблицы

CREATE TABLE "content" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
"title" TEXT NOT NULL, 
"category" INTEGER NOT NULL,
"directians" TEXT NOT NULL,
"time" INTEGER,
"img" TEXT,
"autor" TEXT,
"datetime" DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE ("title") ON CONFLICT REPLACE)

    


Ответы

Ответ 1



Если значение ID увеличивается на единицу, то значит что данные, на самом деле, добавляются, а если быть точнее, то вновь добавляемые данные заменяют предыдущие значения. Об этом поведении говорит строка: UNIQUE ("title") ON CONFLICT REPLACE А для того, чтобы запретить добавление одинаковых данных и соответственно увеличения ID на единицу, нужно просто заменить поведение при конфликтных случаях с этого: UNIQUE ("title") ON CONFLICT REPLACE на вот это: UNIQUE ("title") ON CONFLICT IGNORE Таким образом, вновь добавляемые данные будут игнорироваться и добавление не сработает.

Ответ 2



На php $sth = $db->prepare("SELECT COUNT(*) FROM content WHERE title=?"); $sth->execute(array($title)); $result = $sth->fetchColumn(); if ($result) { $db->prepare("UPDATE ..."); } else { $db->prepare("INSERT ..."); } На mysql CREATE TABLE content ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL UNIQUE, title VARCHAR(255) NOT NULL, UNIQUE (title)); INSERT INTO content (title) VALUES ('1st Street'); INSERT INTO test.Content (title) VALUES ('1st Street') ON DUPLICATE KEY UPDATE title='2st Street'; Индекс не меняется, проверял лично на MySql.

Ответ 3



Причина увеличения Id банальна, в схеме таблицы которую вы привели задекларировано поведение при возникновении конфликта обновлять запись, то есть добавить новую и удалить старую. От этого и возникает изменение Id записи. Нужно изменить ограничение "title" поля таблицы. В зависимости от поведения которое вы хотите получить нужно либо откатывать всю транзакцию или только конфликтующую инструкцию и уже потом обрабатывать в коде исключение (ссылка на документацию): UNIQUE ("title") ON CONFLICT ROLLBACK или UNIQUE ("title") ON CONFLICT ABORT "ON CONFLICT ABORT" - это поведение по умолчанию в sqlite Полное описание структуры таблицы: CREATE TABLE "content" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, "title" TEXT NOT NULL, "category" INTEGER NOT NULL, "directians" TEXT NOT NULL, "time" INTEGER, "img" TEXT, "autor" TEXT, "datetime" DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE ("title") ON CONFLICT ABORT) Если это тот случай когда нельзя изменить схему таблицы (хотя наврядли), то нужно перенести проверку существования уникального "title" в код, но это несёт свои риски в многопоточной записи в таблицу.

Ответ 4



Хм... Может быть реализовывать по банальному по типу аналогии простых cms движков. Проверять на существования запись по title При создании записи, возвращать созданный автоинкремент (IDENT_CURRENT, LAST_INSERT_ID) и при следующих запросах обновлять запись или зная что авто инкремент мы получили сообщить о том что запись существует. Также можно сделать защиту на стороне клиента от повторных случайных нажатий с помощью javascript. Сделав кнопку не активной в течении N секунд.

Ответ 5



Не сильно знаком с SQLite, но вот что удалось нагуглить: Можно попробовать контролировать автоинкремент самостоятельно, например, через COALESCE вот так: INSERT OR REPLACE INTO "content" (id, title, category, directians, time, img, autor, datetime) VALUES( COALESCE( SELECT id FROM "content" WHERE title={title}, --если такой id существует оставляем его SELECT last_insert_rowid() FROM "content" -- если нет, вставляем по автоинкременту ), {title}, {category}, {directians}, {time}, {img}, {autor}, {datetime} ) source

Ответ 6



Правильно сделать - это оставить как есть т.е если id - увеличивается когда даже запрос не прошел -это нормально, если вам нужен порядковый номер то вы можете добавить дополнительное поле для этого, или если при выводе нужно нумеровать записи...то сортируете по id а номер пишите просто порядковый номер строки из выборки - так правильней. Но, если вам нужно по какимто из своих соображений именно так , то решение следующее: INSERT INTO CONTENT (id, title) SELECT max(id) + 1, 'your value' from content

Комментариев нет:

Отправить комментарий