Шрифт:
SELECT COL1, SUM(COL2), COUNT(*) FROM TABLEA
GROUP BY COL1;
Подробности использования COUNT С агрегированием см. в главе 23.
Не используйте SELECT COUNT(*) как способ проверки существования строк, соответствующих некоторому критерию. Такая техника часто обнаруживается в приложениях, которые были переведены в Firebird из основанных на файлах базах данных с блокировкой таблиц, таких как Paradox или MySQL. От этой техники нужно отказаться. Вместо этого используйте функциональный предикат EXISTS, который был разработан для этих целей и является очень быстрым. См. в следующей главе подробности об EXISTS и других функциональных предикатах.
Другая техника, от которой нужно отказаться в Firebird, это использование COUNT(*) и прибавление единицы для "генерации" значения первичного ключа. Это ненадежно в любой многопользовательской СУБД, которая изолирует параллельные задачи. В Firebird это к тому же выполняется крайне медленно, потому что система управления таблицей не имеет "файла записей", которые могли бы быть подсчитаны методами управления файлами на компьютере.
Используйте генераторы для любых целей, которые преследуют уникальность числовых последовательностей. Подробнее о генераторах см .разд. "Генераторы" главы 9.
Результатом COUNT никогда не будет NULL, потому что он подсчитывает строки. Если счетчик будет использован для пустого набора, он вернет ноль. Он никогда не может быть отрицательным.
COUNT(*) для таблицы подсчитывает все строки без проверки существования данных в столбцах. Оптимизатор может использовать индекс, если запрос содержит соответствующее условие WHERE.
Например, оператор
SELECT COUNT(*) FROM EMPLOYEE
WHERE LAST_NAME BETWEEN 'A%' AND 'M%';
может быть чуть менее дорогим, если существует индекс для LAST_NAME.
COUNT (имя-столбца) подсчитывает только строки, где имя-столбца не является NULL.
COUNT (DISTINCT имя-столбца) подсчитывает только отличающиеся значения в этом столбце. То есть все повторения одного и того же значения учитываются как один элемент.
в COUNT (DISTINCT ...), если столбец допускает значение NULL, все строки, содержащие в этом столбце NULL, исключаются из подсчета. Если вы должны их сосчитать, это может быть выполнено "хакерским" способом:
SELECT COUNT (DISTINCT TABLE.COLX) +
(SELECT COUNT(*) FROM RDB$DATABASE
WHERE EXISTS(SELECT * FROM TABLE T
WHERE T.COLX IS NULL))
FROM TABLE
Оператор INSERT
Оператор INSERT используется для добавления строк в одну таблицу. SQL не позволяет в одном операторе INSERT добавлять строки более чем в одну таблицу.
При некоторых условиях оператор INSERT может работать с просмотрами. Обсуждение просмотров, для которых можно применять добавление данных в лежащие в основе просмотра таблицы, см. в главе 24.
Оператор INSERT имеет две основные формы передачи значений в список входных столбцов.
Используйте следующую форму для добавления списка констант:
INSERT INTO имя-таблицы | имя-просмотра (<список столбцов>)
VALUES (<соответствующей список значений>)
Следующая форма используется для добавления из встроенного запроса:
INSERT INTO <таблица> (<список столбцов>)
SELECT [[FIRST m] [SKIP n]] <соответствующий список значений из другого набора>
[ORDER BY <встроенный столбец (столбцы)> [DESC]]
В следующем примере предложение INSERT INTO определяет входной набор для таблицы TABLEB, а предложение SELECT определяет соответствующий встроенный запрос к таблице TABLEA для получения значений для входного набора:
INSERT INTO TABLEB(COLA, COLB, COLC)
SELECT COL1, COL2, COL3 FROM TABLEA;
! ! !
ПРИМЕЧАНИЕ. He существует возможности добавлять данные во встроенный запрос.
. ! .
Добавление данных в столбцы BLOB
Техника INSERT INTO ... SELECT напрямую передает столбец BLOB В столбец BLOB. Как правило, если вам нужно добавить столбец BLOB как часть списка VALUES, он должен конструироваться клиентским приложением с использованием функций и структур API. В приложениях DSQL такие данные обычно передаются в виде потоков (stream). Размер сегмента может быть проигнорирован везде, кроме приложений ESQL.