Вверх ↑
Ответов: 1891
Рейтинг: 110
#1: 2007-06-12 02:06:06 ЛС | профиль | цитата
nesco, писал(а):
Я понял так, что null для поля с AUTOINCREMENT'ом означает приращение на один.


Это дезинформация, т.к. когда значение поля равно NULL, это означает, что программа базы данных специально промаркировала это поле как не имеющее никакого значения для этой строки (или записи). Это отличается от просто назначения полю значения нуля или пробела, которые база данных будет обрабатывать также как и любое другое значение. Точно также, как NULL не является техническим значением, оно не имеет и типа данных.

Перевод с сайта SQLite писал(а):
Согласно стандарту SQL, "PRIMARY KEY" должен подразумевать "NOT NULL". К сожалению, в силу застаревшей ошибки кодирования, SQLite не соответствует этому требованию. SQLite допускает значения "NULL" в столбце "PRIMARY KEY". Мы хотели исправить SQLite в соответствии со стандартом (и мы могли это сделать), но выяснилось, что за время существования этого бага, многие пользователи восприняли его как фичу, и мы поостереглись фиксить этот баг, дабы в будущем не ломать коды пользователей. Итак, сейчас мы вынуждены допускать "NULL"-ы в столбцах "PRIMARY KEY". Однако, разработчики должны сознавать, что в будущем мы, возможно, изменим SQLite в соответствии со стандартом SQL и, следовательно, новые программы следует разрабатывать с учетом этого.



Tad писал(а):
NULL он и в Африке null, но в SQLite не всегда


Tad, почитай книжки по стандарту SQL, а потом спорь. NULL - значит пустой и не может быть чем-то другим

[size=-2]------ Добавлено в 01:56
nesco, писал(а):
Под транзакциями понимается тело цикла модификации, при успешном окончании которого, модификация считается успешно завершенной, иначе база не меняется вообще, я правильно понял? Значит приложение, записывающее в базу должно начинать цикл модификации с запроса BEGIN TRANSACTION, или это не обязательно, при условии, что другое приложение открывает базу только на просмотр и поиск (или уже ищет в базе до 100 000 тысяч записей). И чем операторные скобки BEGIN TRANSACTION должны заканчиваться -- END, COMMIT или ROLLBACK [TRANSACTION]?


BEGIN TRANSACTION

Код:
sql-оператор ::= BEGIN [ DEFERRED | IMMEDIATE | EXCLUSIVE ] [TRANSACTION [имя]]
sql-оператор ::= END [TRANSACTION [имя]]
sql-оператор ::= COMMIT [TRANSACTION [имя]]
sql-оператор ::= ROLLBACK [TRANSACTION [имя]]


Начиная с версии 2.0 SQLite поддерживает транзакции с откатом ("rollback") и атомарным подтверждением ("commit").

Опциональное имя транзакции игнорируется. В настоящее время SQLite не допускает вложенных транзакций.

База данных может быть изменена только в контексте транзакции. Любая команда, изменяющая базу данных (в основном, - это любая команда SQL, кроме "SELECT") автоматически начнет транзакцию, если та еще не начата. После выполнения команды автоматически начатая транзакция будет подтверждена ("committed").

Транзакция может быть начата вручную с помощью команды "BEGIN". Такая транзакция обычно сохраняется вплоть до следующей команды "COMMIT" или "ROLLBACK". Но, кроме того, "ROLLBACK" транзакции произойдет в случае закрытия базы данных, или если случится ошибка и "ROLLBACK" окажется способом разрешить конфликт. Чтобы больше узнать об алгоритме разрешения конфликтов "ROLLBACK", смотрите пункт "ON CONFLICT" этой документации.

В SQLite версии 3.0.8 и старше транзакции могут быть отложенными ("deferred"), немедленными ("immediate") или исключительными ("exclusive"). Отложенность означает, что база данных никак не блокируется до первого доступа к ней. Таким образом, при отложенной транзакции инструкция "BEGIN" ничего сама не делает. Блокировка не произойдет до первой операции чтения или записи. Первая же операция чтения создаст "SHARED" блокировку, а первая операция записи создаст "RESERVED" блокировку. Так как блокировка отложена до необходимости, другая нить или процесс могут создать отдельную транзакцию и выполнить запись в базу после "BEGIN"-а в текущей нити. Если транзакция является немедленной, "RESERVED" блокировка накладывается на все базы как только выполняется команда "BEGIN" независимо от того, когда будет использована база данных. После "BEGIN IMMEDIATE" вы можете быть уверены, что никакая нитка или процесс не смогут писать в базу и не смогут выполнить "BEGIN IMMEDIATE" или "BEGIN EXCLUSIVE". Тем не менее, другие процессы смогут продолжать читать базу данных. Исключительная транзакция устанавливает "EXCLUSIVE" блокировку на все базы данных. После "BEGIN EXCLUSIVE" вы можете быть уверены, что ни одна нитка или процесс не могут читать или писать в базу пока продолжается транзакция.

Описание блокировок "SHARED", "RESERVED" и "EXCLUSIVE" доступно здесь.

В SQLite версии 3.0.8 по умолчанию применяется отложенная транзакция. Для SQLite версий 3.0.0 - 3.0.7 отложенная транзакция является единственной возможной. В SQLite версии 2.8 и в более ранних все транзакции были исключительными.

Команда "COMMIT" не выполняется, пока не будут выполнены все, выполняющиеся в данный момент, команды SQL. Так, если "COMMIT" запускается в момент выполнения двух или более запросов "SELECT", он ничего не будет делать до тех пор, пока не закончится выполнение всех запросов "SELECT".

Попытка выполнить "COMMIT" может вернуть код "SQLITE_BUSY". Это означает, что другая нить или процесс читают из базы, и это помешало ее изменить. Когда "COMMIT" терпит неудачу подобным образом, транзакция остается активной, и "COMMIT" может быть повторен позже, когда чтение закончится.

[size=-2]------ Добавлено в 02:06
nesco, писал(а):
Вот про триггер подробнее можно?


CREATE TRIGGER

Код:
sql-оператор ::= CREATE [TEMP | TEMPORARY]
TRIGGER [IF NOT EXISTS] имя-триггера [ BEFORE | AFTER ]
событие-базы ON [имя-базы .] имя-таблицы
действие-триггера
sql-оператор ::= CREATE [TEMP | TEMPORARY]
TRIGGER [IF NOT EXISTS] имя-триггера INSTEAD OF
событие-базы ON [имя-базы .] имя-вьюхи
действие-триггера
событие-базы ::= DELETE |
INSERT |
UPDATE |
UPDATE OF список-столбцов
действие-триггера ::= [ FOR EACH ROW | FOR EACH STATEMENT ] [ WHEN выражение ]
BEGIN
шаг-триггера ; [ шаг-триггера ; ]*
END
шаг-триггера ::= оператор-update |
оператор-insert |
оператор-delete |
оператор-select


Оператор "CREATE TRIGGER" используется для добавления триггеров в схему базы данных. Триггеры - это операции (действие-триггера) на базе данных, которые исполняются автоматически, при возникновении указанного события (событие-базы).

В зависимости от описания, триггер может запускаться всякий раз, когда случается "DELETE", "INSERT" или "UPDATE" определенной таблицы базы, или всякий раз, когда при изменении таблицы случается "UPDATE" одного или нескольких указанных столбцов.

В настоящее время SQLite поддерживает только триггеры "FOR EACH ROW", и не поддерживает триггеры "FOR EACH STATEMENT". Поэтому, необязательно явно указывать "FOR EACH ROW". "FOR EACH ROW" предполагает, что при запуске триггера SQL-операторы, специфицированные как "шаг-триггера", могут выполняться (в зависимости от пункта "WHEN") для каждой вставляемой, изменяемой или удаляемой строки в базе.

Элементы вставляемой, удаляемой или изменяемой строки доступны в пунктах "WHEN" и "шаг-триггера" с помощью ссылочных форм "NEW.имя-столбца" и "OLD.имя-столбца", где "имя-столбца" есть имя того столбца таблицы, к которому осуществляется доступ из триггера. Ссылки "OLD" и "NEW" могут использоваться только в триггерах и в "событиях-триггера", которым они соответствуют, как указано ниже:


* INSERT - Допустима ссылка "NEW"
* UPDATE - Допустимы ссылки "NEW" и "OLD"
* DELETE - Допустима ссылка "OLD"
Если указан пункт "WHEN", SQL-операторы, специфицированные как "шаг-триггера", выполняются только на тех строках, на которых выражение "WHEN" истинно. Если пункт "WHEN" не указан, то SQL-операторы выполняются на всех строках.

Специфицированное время-триггера ("BEFORE" или "AFTER") определяет, когда должны выполняться шаги-триггера относительно вставки, изменения или удаления данной строки.

Пункт "ON CONFLICT" может быть специфицирован как часть шага-триггера "UPDATE" или "INSERT". Но если пункт "ON CONFLICT" специфицирован как часть оператора, вызывающего выполнение триггера, то эта политика разрешения конфликтов используется вместо указанной в триггере.

Триггеры автоматически удаляются при удалении таблицы, с которой они ассоциированы.

Так же как на обыкновенных таблицах триггеры могут быть созданы на вьюхах с использованием "INSTEAD OF" в операторе "CREATE TRIGGER". Если на вьюхе определен один или несколько триггеров "ON INSERT", "ON DELETE" или "ON UPDATE", то, соответственно, выполнение на этой вьюхе операторов "INSERT", "DELETE" или "UPDATE" не является ошибкой. Таким образом, выполнение "INSERT", "DELETE" или "UPDATE" на вьюхе становится возможным с помощью ассоциированных с ней триггеров. Действительная таблица, на которую ссылается вьюха, не модифицируется (если только это не заложено явно в триггер).

Пример:

Предположим, что записи о клиентах хранятся в таблице "customers", и что записи о заказах хранятся в таблице "orders". Следующий триггер гарантирует, что когда клиент меняет свой адрес, все соответствующие ему заказы переназначаются:

Код:
CREATE TRIGGER update_customer_address UPDATE OF address ON customers
BEGIN
UPDATE orders SET address = new.address WHERE customer_name = old.name;
END;


С созданием этого триггера, выполнение команды

Код:
UPDATE customers SET address = '1 Main St.' WHERE name = 'Jack Jones';


автоматически приведет к выполнению следующей:

Код:
UPDATE orders SET address = '1 Main St.' WHERE customer_name = 'Jack Jones';


Заметим также, что триггеры могут вести себя странно, если создаются на таблицах с полями "INTEGER PRIMARY KEY". Если триггер "BEFORE" модифицирует поле "INTEGER PRIMARY KEY" в строке, которая впоследствии должна быть изменена командой, которая влечет запуск этого триггера, то изменение может не произойти. Чтобы это обойти, можно декларировать столбец таблицы как "PRIMARY KEY" вместо "INTEGER PRIMARY KEY".

Специальная SQL-функция "RAISE()" может быть использована внутри программы-триггера в следующем синтаксисе:

Код:
функция-raise ::= RAISE ( ABORT, сообщение-об-ошибке ) |
RAISE ( FAIL, сообщение-об-ошибке ) |
RAISE ( ROLLBACK, сообщение-об-ошибке ) |
RAISE ( IGNORE )


Если во время выполнения текущей программы-триггера она вызывается в одной из первых трех форм, то выполняется указанный обработчик "ON CONFLICT" (то есть "ABORT", "FAIL" или "ROLLBACK") и текущий запрос убивается. Ошибочный код "SQLITE_CONSTRAINT" возвращается пользователю вместе с указанным сообщением об ошибке.

Когда вызывается "RAISE(IGNORE)", остаток текущей программы триггера, оператор, ставший причиной запуска триггера, и последующие программы триггера, которые должны были бы выполниться, не будут выполнены. Изменения базы данных не будут откачены. Если оператор, ставший причиной запуска программы триггера, сам является частью какой-то программы триггера, то эта вторая программа триггера продолжит выполнение с начала следующего шага.

Триггеры могут быть удалены с помощью оператора "DROP TRIGGER".
карма: 0
%time%
0