Приветствуем, Гость! Регистрация

SQL. Глупых (и не очень) вопросов тред
#1
Задача: иметь в нескольких таблицах общий уникальный для *всех* таблиц (не для каждой отдельно, с этим справится просто `UNIQUE`) `INTEGER`.

Допустим, в одной таблице есть две записи с идентификаторами (не `rowid`) 1 и 2, я хочу при добавлении двух записей в другую таблицу получить 3 и 4 (если в запросе не указано иного) для этих новых записей, а при добавлении ещё двух в третью — 5 и 6, ну и при добавлении снова в первую — 7 и 8 и так далее.

*// MySQL, Postgres и прочие тоже годятся, мне бы только понять что искать.*
Правила форума
[Новичкам] Как правильно задавать вопросы, чтобы Вам помогли

«Буду бить аккуратно, но сильно!» © Лёлик, х/ф «Бриллиантовая рука»
Ответ
#2
Довольно странная хотелка, но можно сделать на триггерах (SQLite3) как-то так:
```sql
CREATE TABLE "glob" (
"id" INTEGER NOT NULL PRIMARY KEY,
"gid" INTEGER NOT NULL UNIQUE DEFAULT 1
);

CREATE TABLE "first_rel" (
"id" INTEGER NOT NULL PRIMARY KEY,
"gid" INTEGER DEFAULT NULL,
"data" TEXT NOT NULL
);
CREATE TABLE "second_rel" (
"id" INTEGER NOT NULL PRIMARY KEY,
"gid" INTEGER DEFAULT NULL,
"data" TEXT NOT NULL
);

CREATE TRIGGER "first_rel_glob_inc"
AFTER INSERT ON "first_rel" WHEN NEW."gid" IS NULL
BEGIN
UPDATE "first_rel"
SET "gid" = (SELECT "gid" FROM "glob" ORDER BY "id" LIMIT 1) WHERE "id" = NEW."id";
UPDATE "glob" SET "gid" = "gid" + 1;
END;
CREATE TRIGGER "second_rel_glob_inc"
AFTER INSERT ON "second_rel" WHEN NEW."gid" IS NULL
BEGIN
UPDATE "second_rel"
SET "gid" = (SELECT "gid" FROM "glob" ORDER BY "id" LIMIT 1) WHERE "id" = NEW."id";
UPDATE "glob" SET "gid" = "gid" + 1;
END;

INSERT INTO "glob" ("gid") VALUES (1);
```
И получился какой-то кошмар. Но можно же %).
Ответ
#3
XRevan86 post_id=817 time=1589764384 user_id=76 Написал:Довольно странная хотелка

Теперь я понимаю, что это плохая идея (плюс на триггерах это скажется на отзывчивости).

XRevan86 post_id=817 time=1589764384 user_id=76 Написал:```sql
UPDATE "first_rel"
SET "gid" = (SELECT "gid" FROM "glob" LIMIT 1) WHERE "id" = NEW."id";
```

Зачем здесь `SELECT` с `LIMIT 1`? Без `ORDER BY "gid" DESC` оно всегда выдаст первый (с `id=1`) gid, разве нет?
Правила форума
[Новичкам] Как правильно задавать вопросы, чтобы Вам помогли

«Буду бить аккуратно, но сильно!» © Лёлик, х/ф «Бриллиантовая рука»
Ответ
#4
Цитата: Теперь я понимаю, что это плохая идея (плюс на триггерах это скажется на отзывчивости).

Ещё какая. И плохо связывается с теорией отношений.
Цитата: Зачем здесь ```SELECT``` с ```LIMIT 1```? Без ```ORDER BY "gid" DESC``` оно всегда выдаст первый (с id=1) gid, разве нет?

Эм, что? Он выдаст все записи.
Их, правда, и так должна быть только одна штука, но всё равно все.
А сортировка на размер выдачи не влияет никак.
Ответ
#5
XRevan86 post_id=825 time=1589823073 user_id=76 Написал:Эм, что? Он выдаст все записи.

Я что-то проглядел, что у тебя там только одна запись, и ты её инкрементишь. У меня мозг пухнет от всего этого, поэтому я либо туплю, либо *сильно* туплю.

XRevan86 post_id=825 time=1589823073 user_id=76 Написал:Их, правда, и так должна быть только одна штука, но всё равно все.

Цитата: ```sql
SELECT "gid" FROM "glob" LIMIT 1;
```

Сколько бы ни было, `LIMIT 1` ограничит выдачу первым одним результатом. Без прочих условий это будет наименьший `PRIMARY KEY` (в данном случае `id=1`). Это не имеет значения если запись всего одна, но имеет смысл накатить условий, чтобы не отстрелить себе что-нибудь, если в таблицу прилетит ещё запись с `PRIMARY KEY` меньше существующего, например `0`, так как сортировка идёт по нему.
Правила форума
[Новичкам] Как правильно задавать вопросы, чтобы Вам помогли

«Буду бить аккуратно, но сильно!» © Лёлик, х/ф «Бриллиантовая рука»
Ответ
#6
Цитата: Сколько бы ни было, ```LIMIT 1``` ограничит выдачу первым одним результатом.

Да я в курсе, я же сам его туда и вписал %).
Это было всё ещё про "Он выдаст все записи".

А, теперь я понял, что ты имел в виду.
SQLite не выдаст ошибку, если подзапрос даст больше одного кортежа, о сём я не вспомнил.
Цитата: Зачем здесь ```SELECT``` с ```LIMIT 1```?

В иной СУБД иначе могла бы быть ошибка в случае, если записей больше одной %).
Что, впрочем, в данном случае могло бы быть защитой от вмешательства в отношение ```glob```. Ну ладно.
Ответ
#7
XRevan86 post_id=827 time=1589846974 user_id=76 Написал:В иной СУБД иначе могла бы быть ошибка в случае, если записей больше одной

[Потыкав тесты…] А в Sqlite3 в этой конструкции оно возьмёт первую запись без ошибок.

XRevan86 post_id=827 time=1589846974 user_id=76 Написал:Что, впрочем, в данном случае могло бы быть защитой от вмешательства в отношение glob.

Не могло, если была добавлена запись с `PRIMARY KEY` меньше, о чём я уже писал:

```sql
INSERT INTO glob (rowid, id, gid) VALUES (-100500, -100500, -1);
```
Правила форума
[Новичкам] Как правильно задавать вопросы, чтобы Вам помогли

«Буду бить аккуратно, но сильно!» © Лёлик, х/ф «Бриллиантовая рука»
Ответ


Перейти к форуму:


Пользователи, просматривающие эту тему: 1 Гость(ей)