© Copyright Максим Мошков, 1991-1995
                                   moshkow@ipsun.ras.ru

Операторы  языка  SQL  используются  во  всех  инструментальных
средствах  разработки  Informix  (Informix-SQL,   Informix-4GL,
Informix-ESQL/C  и  др.).  Для  каждого  инструмента характерны
определенные особенности использования SQL, которые  описаны  в
соответствующей документации. В этом разделе даются сведения об
применении операторов SQL в среде разработки Informix-4GL.



Программа,  написанная  на 4GL использует предписания языка SQL
(Структурного Языка Запросов) для манипуляций с базой данных.

Формат записи операторов SQL свободный. Можно писать все подряд
на одной строке, один оператор  на  нескольких  строках,  слова
операторов  можно разделять произвольным количеством пробелов и
комментариев. Никакими значками (типа ;) операторы разделять не
нужно. Окончание операторов определяется по контексту.

Примечание:  если вы записываете предписания SQL не в программе
4GL а в среде INFORMIX-SQL, то  разделять  операторы  точкой  с
запятой (;) необходимо.

Весь  набор  ключевых  слов языка SQL зарезервирован, их нельзя
занимать для других целей (на имена объектов и переменных SQL и
4GL).

Компилятору  языка безразлично, большими или маленькими буквами
пишутся операторы. Он их не различает.

Комментарии обозначаются знаками { комментарий },
или знаком -- (два знака минус) до конца строки.



Идентификатор  (имя объекта)  -  это  слово, состоящее из букв,
цифр, и знаков подчеркивания (_), начинающееся с буквы или зна-
ка (_). В INFORMIX-4GL не различаются маленькие и большие  бук-
вы. Поэтому i_Un1023Tt и I_UN1023TT - одно и тоже имя.

Имя базы данных не длиннее 10.

Имена    прочих    объектов    SQL    -    таблиц,    столбцов,
view(псевдотаблиц) , синонимов - не длиннее 18.



   SQL содержит 4 группы операторов:

 - Операторы описания данных:
CREATE, DROP, ALTER и др.

 - Операторы манипуляции данными:
INSERT, DELETE, SELECT, UPDATE и др.

 - Операторы задания прав доступа в базе данных:
GRANT / REVOKE ,  LOCK / UNLOCK ,  SET LOCK MODE

 - Операторы защиты, восстановления данных и прочие операторы.

Их обзором мы сейчас и займемся, по порядку.



Операторы описания данных предназначены  для  описания  (созда-
ния),  изменения  описания  и уничтожения объектов базы данных.

В SQL различаются  следующие виды объектов:
    база данных (database);
    таблица (table);
    столбец (column);
    индекс (index);
    снимок (view);
    синоним (synonym).

Каждый  объект  имеет  собственное  имя - идентификатор. Каждый
объект имеет владелеца - т.е. того  пользователя,  который  его
создал. Имя объекта можно уточнять с помощью имени его владель-
ца (owner-name) в такой форме: moshkow.table1

Ниже  приводятся примеры использования всех операторов описания
данных.  Полный  же  их  синтаксис  можно  найти   в   "Кратком
справочнике  по  4GL"  (см.  Приложения),  либо  в  "Справочном
руководстве по Informix-4GL".

Создание базы данных.
---------------------------------------------------------------
CREATE DATABASE zawod
---------------------------------------------------------------

В любой момент времени вы можете иметь доступ к объектами толь-
ко  одной  - ТЕКУЩЕЙ (CURRENT) - базы данных. Оператор DATABASE
делает новую базу текущей, закрывая при этом доступ к  объектам
предыдущей  текущей базы. Оператор CLOSE DATABASE просто закры-
вает текущую базу данных.
---------------------------------------------------------------
DATABASE zawod
  . . .                 # текущей является база zawod
DATABASE stanciq
  . . .                 # текущей является база stanciq
CLOSE DATABASE
                        # текущей базы нет
---------------------------------------------------------------

Создаются таблицы kadry и ceh, содержащие столбцы разных типов.
---------------------------------------------------------------
CREATE TABLE  kadry    (
 nomerceh  INT,
 tabnom    SERIAL ,
 fio       CHAR(20) UNIQUE,
 zarplata  MONEY(16,2),
 datarovd  DATE,
 pribytie  DATETIME year TO minute )

CREATE TABLE ceh ( nomerceh int, nameceh char(20) )
---------------------------------------------------------------

В уже существующей таблице мы можем поменять тип столбца, доба-
вить новый, уничтожить старый.
---------------------------------------------------------------
ALTER TABLE kadry ADD  (dolvnostx  CHAR(20)  BEFORE  zarplata),
DROP(pribytie),  ADD  CONSTRAINT UNIQUE(tabnom, fio) CONSTRAINT
tabnomfio

ALTER TABLE items MODIFY (manu_code char(4))
---------------------------------------------------------------
Изменение структуры таблицы приводит к физическому преобразова-
нию  данных  в  ней.  Если изменен тип столбца, то данные в нем
преобразуются к новому типу, и если это невозможно осуществить,
то оператор ALTER "валится" с кодом ошибки, а  таблица остается
в неизмененном состоянии.

View  - "псевдо" таблица, базируется на существующих таблицах.
---------------------------------------------------------------
CREATE VIEW poor AS SELECT tabnom, fio, datarovd FROM kadry
   WHERE zarplata < 120
# создано  view  - "псевдотаблица" из трех столбцов  содержащая
# строки из таблицы kadry, в которых zarplata меньше 120 рублей.
---------------------------------------------------------------
Ведет себя точно так же, как настоящая таблица, только место на
диске под нее не отводятся, поскольку данные, лежащие в ней  на
самом деле хранятся в таблице, на которой это view базируется.

Индекс - дополнительная структура к столбцам таблицы, нужен для
ускорения поиска значений в столбце.
---------------------------------------------------------------
CREATE  UNIQUE INDEX indkdtb ON kadry (tabnom)
#  создан  индекс  для  столбца tabnom из таблицы kadry. Индекс
#  уникальный,  значит  в столбце не могут появиться одинаковые
#  значения.
---------------------------------------------------------------

Мы можем  физически упорядочить таблицу в соответствии с индек-
сом. В кластеризованной таблице  SELECT работает быстрее.
---------------------------------------------------------------
ALTER INDEX indkdtb TO  CLUSTER
---------------------------------------------------------------

Имена  столбцов в разных таблицах могут совпадать. Если в каком
либо операторе SQL упоминаются два столбца с одинаковыми назва-
ниями, то их нужно уточнять именами таблиц, их содержащих.  Пе-
ред именем любого объекта можно (а иногда и необходимо) указать
имя  его владельца (owner-name) - входное имя пользователя, ко-
торый создал (CREATE) этот объект.
---------------------------------------------------------------
kadry.nomerceh     #    столбец nomerceh из таблицы kadry
ceh.nomerceh       #    столбец nomerceh из таблицы ceh
iwanow.table1.c1   #    столбец c1 из таблицы table1,  владель-
                   #    цем которой является iwanow
moshkow.table1.c1  #    столбец c1 из другой (!) таблицы  -
                   #    таблицы table1, владельцем которой  яв-
                   #    ляется moshkow
---------------------------------------------------------------

Синоним для имени таблицы используется для сокращения записи.
---------------------------------------------------------------
CREATE SYNONYM t1 FOR petrow.sostoqnie_postow
---------------------------------------------------------------
Теперь повсюду можно  (хотя  и  не  обязательно)  вместо  имени
petrow.sostoqnie_postow использовать имя t1.

База данных может иметь системный журнал транзакций (logfile).
---------------------------------------------------------------
START  DATABASE zawod  WITH LOG IN "/udd/moshkow/logfile/zawod"
---------------------------------------------------------------

Если нет журнала  транзакций  для  всей базы данных, то для от-
дельных таблиц в базе с той же целью можно создать audit trail.
---------------------------------------------------------------
CREATE AUDIT FOR kadry IN "/udd/moshkow/kadry.audit"
---------------------------------------------------------------

Естественно, что любой созданный в  базе  данных  объект  можно
уничтожить.  Надо только помнить, что операторы описания данных
не откатываются назад, а потому если вы уничтожили таблицу, или
базу данных то знайте, что это навсегда.
---------------------------------------------------------------
DROP VIEW poor  # Уничтожается только view. С данными в  табли-
                #  цах,  на  которых оно базировалось ничего не
                #  происходит.
DROP TABLE   kadry      # уничтожает таблицу вместе с данными.
DROP INDEX   indkdtb
DROP SYNONYM t1
DROP DATABASE zawod # уничтожает базу вместе со всеми данными и
                    # системным журналом
---------------------------------------------------------------



Выдавать и забирать права доступа к таблице может владелец таб-
лицы, Администратор Базы Данных (имеющий DBA права), а  так  же
пользователь, которому было выдано право выдавать права (Опера-
тором GRANT WITH GRANT OPTIONS)
---------------------------------------------------------------
REVOKE ALL ON customer FROM PUBLIC
GRANT ALL ON customer TO iwanow, petrow WITH GRANT OPTION

GRANT UPDATE(fname,lname,company, sity),SELECT
   ON customer TO PUBLIC

REVOKE CONNECT  FROM sidorowa, root
REVOKE DBA FROM ivanov
---------------------------------------------------------------
Отобрать у вас права DBA (если вы, конечно, им являетесь) может
только другой DBA.

На  время транзакции все измененные строки автоматически блоки-
руются системой от изменения (но не от  просмотра).  Вы  можете
явно  локировать  всю  таблицу  целиком, тогда система не будет
блокировать строки по отдельности. Вы можете блокировать табли-
цу целиком не только от изменения но и от просмотра.
---------------------------------------------------------------
BEGIN WORK
LOCK TABLE kadry
        . . .
UNLOCK TABLE kadry
        . . .
LOCK TABLE kadry EXCLUSIVE
---------------------------------------------------------------

Если ваш оператор  пытается  записать  в  блокированную  другим
пользователем  строку, то оператор "сваливается". Вы можете ус-
тановить  для  своей  программы  режим  "Ждать  разблокирования
строк".
---------------------------------------------------------------
SET LOCK MODE TO WAIT
---------------------------------------------------------------



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

Поскольку за все хорошее приходится платить, наличие системного
журнала у базы данных вызывает заметный рост накладных расходов
и  замедление  работы  запросов.  К тому же при активной работе
с  базой системный журнал быстро "распухает". За ним нужно сле-
дить и периодически чистить.

Указать базе новый системный журнал.
---------------------------------------------------------------
START  DATABASE zawod  WITH LOG IN "/ARM/log/zawod"
---------------------------------------------------------------

Восстанавливают  разрушенную (например из-за сбоя оборудования)
базу данных так:
---------------------------------------------------------------
         В среде UNIX
1. Уничтожают остатки базы.
2. Заливают вместо них копию базы с ленты (например,  недельной
давности) используя команду cpio или утилиту INFORMIX dbimport.
3.      Входят в среду INFORMIX и выполняют операторы:
   DATABASE kadry  EXCLUSIVE       # чтобы никто не лез
   ROLLFORWARD DATABASE kadry      # прогнать базу вперед
                                   # по системному журналу
   CLOSE DATABASE                  # теперь всем можно работать
---------------------------------------------------------------

Транзакция
---------------------------------------------------------------
BEGIN WORK      # начать транзакцию
   . . .        # операторы

IF все нормально THEN COMMIT WORK
ELSE                  ROLLBACK WORK
END IF
---------------------------------------------------------------
Если  во время транзакции программа "свалилась" то INFORMIX ав-
томатически сделает откатку.




Следующая группа  операторов  предназначена для манипулирования
данными в таблицах. В  нее  входят  операторы  выбора  (SELECT)
строк  из  таблицы  (или  таблиц), уничтожения (DELETE) строк в
таблице, вставки (INSERT) строк, и изменения (UPDATE)  значений
в существующих в таблице строках.



Уничтожить в таблице kadry все строки, в которых номер цеха ра-
вен 4, а фамилия кончается на буквы "ов"
---------------------------------------------------------------
DELETE FROM kadry WHERE ceh=4 AND fio MATCHES "*ов"
---------------------------------------------------------------
В результате из списков будут вычеркнуты  работники  4-го  цеха
"Петров", "Иванов", "Сидоров" и т.п
Как видим, INFORMIX предоставляет националистически озабоченным
руководителям мощные средства для воплощения в жизнь своих идей.

А этот  оператор уничтожит ВСЕ строки в таблице kadry, владель-
цем которой является moshkow, но не саму таблицу
---------------------------------------------------------------
DELETE FROM moshkow.kadry
---------------------------------------------------------------



Первый пример находит в таблице kadry строку, в которой столбец
tabnum=345 . Из этой строки берутся только три указаных столбца.
Второй пример выбирает ВСЕ строки из таблицы ceh, и все столбцы.
---------------------------------------------------------------
SELECT fio, dolvn, zarplata FROM kadry WHERE tabnom=345

SELECT * FROM ceh

SELECT kadry.fio, ceh.nameceh WHERE kadry.nomerceh=ceh.nomerceh
---------------------------------------------------------------
Третий  пример  выбирает фамилии работников из таблицы кадры, а
названия цехов, в которых они работают, из таблицы ceh.




может вставить в таблицу одну строку, если используется в форме
INSERT  INTO ... VALUES, а может вставить в таблицу целый набор
строк, выбранных подзапросом SELECT из другой таблицы.
---------------------------------------------------------------
INSERT INTO kadry VALUES (4,0,"Грицько",num,"10/25/1939",NULL)

INSERT INTO customer VALUES (ps_customer.*)
# ps_customer - переменная типа RECORD  -  аналог  структуры  в
# языке Си. Этот оператор вставляет значения элементов записи
# ps_customer в соответствующие поля таблицы customer

INSERT INTO kadry      (tabnom,  fio,  nomerceh,  dolvnostx)
         SELECT  0 , fio, 4, dolvnostx FROM kadryold
                 WHERE nomerceh=3 AND fio IS NOT NULL
#   последний оператор вставляет сразу несколько строк
---------------------------------------------------------------
Если мы хотим, чтобы при вставлении строки в столбец типа SERI-
AL  автоматически заносилось очередное значение счетчика, нужно
вставлять в этот столбец константу 0.
Если не во все столбцы  вставляемой  строки  вносится  значение
(как это сделано в третьем операторе), то незаполненные столбцы
заполняются значением NULL.

В  операторах DELETE, UPDATE, SELECT может присутствовать WHERE
предложение, в котором можно задать условия на строки,  которые
требуется  обработать  (соответственно уничтожить, изменить или
выбрать). Рассмотрим примеры использования WHERE предложения.




меняет значения столбцов, в  строках, удовлетворяющим WHERE ус-
ловию.
---------------------------------------------------------------
UPDATE kadry SET fio="Зыкова" WHERE fio="Гирусова"

UPDATE ceh SET kod_ceha[1,4]=nameceh[5,8]    WHERE
 nomerceh BETWEEN 3 AND 5 OR nameceh IN ("токарный","литейный")
---------------------------------------------------------------
В  таблице ceh в цехах номер 3,4,5 а так же в токарном и литей-
ном  первые четыре символа в коде цеха будут заменены на подст-
року поля nameceh из той же строки.



Предложение WHERE может присутствовать в  любом  из  операторов
DELETE,  UPDATE,  SELECT, когда нужно задать условия на строки,
которые требуется обработать (соответственно, уничтожить, изме-
нить или выбрать). Рассмотрим структуру и примеры использования
предложений WHERE.

В предложении WHERE пишется логическое условие, которое получа-
ется  соединением с помощью логических операторов AND, OR и NOT
элементарных сравнений типа:

    выражение1  <  выражение2,
    выражение1  >= выражение2,  и т.п.,

а так же элементарных сравнений специального вида:

     column-name IS [NOT] NULL
     выраж [NOT] BETWEEN выраж1 AND выраж2
     выраж [NOT] IN (выраж1 , ...  [, ...] )

Можно выяснить, подходит ли символьная строка под  определенный
шаблон,  или нет. Для этого используются две операции сравнения
по шаблону - LIKE  и MATCHES.

      симв-выражение MATCHES "шаблон"
      симв-выражение LIKE "шаблон"

LIKE имеет более простой шаблон.  В нем используются только два
спецсимвола: (%) замещает произвольное количество символов, (_)
замещает ровно один символ. Все  остальные  символы  в  шаблоне
обозначают  сами  себя. Если мы хотим включить в шаблон % или _
отменив их специальный смысл, то перед ними надо поставить ESC-
символ (по умолчанию это (\)).

Допустим нам нужно выбрать  из таблицы tab8 все строки, в кото-
рых символьный столбец string1 содержит символ "+"  а  предпос-
ледняя буква в нем - "Ы". Оператор выборки будет выглядеть так:
---------------------------------------------------------------
SELECT * FROM tab8 WHERE string1 LIKE "%+%Ы_"
---------------------------------------------------------------

MATCHES использует такие спецсимволы шаблона: *,?,[,],^,-.
        *     заменяет любое количество символов
        ?     заменяет один любой символ
      [...]   заменяет один символ из перечисленных в скобках
              возможно указание от и до (-), и не (^)
              [abH] - любой из символов a, b, H
              [^d-z] - любой символ, исключая d,e,f,g, ... ,y,z
        \     отменяет спецсмысл спецсимволов *,?,[,]

Если  вы  хотите  воспользоваться  спецсимволами  как обычными,
примените escape-char. Если escape-char="\", то  \?  обозначает
просто  символ  ?, \* обозначает просто символ *, \\ обозначает
просто символ \ . Зато знак кавычки (")  внутри  шаблона  нужно
обозначать двумя кавычками ("").

Выбрать все данные о заказчиках  в  названии  компании  которых
вторая  буква не лежит в интервале от G до L, а третья буква c.
(Кстати, коды русских букв на БЕСТЕ  идут  подряд, но в отличие
от латинских букв, русские не упорядоченны по алфавиту.)
---------------------------------------------------------------
SELECT * FROM customer WHERE company MATCES"?[^G-L]c*"
---------------------------------------------------------------

Выбрать  все  данные  о  заказчиках в названии компании которых
присутствует вопросительный знак.
---------------------------------------------------------------
SELECT *  FROM customer
        WHERE company MATCHES "*Я?*"  ESCAPE"Я"
---------------------------------------------------------------
В данном примере использовался ESC-символ "Я" для отмены спецс-
мысла символа "?"


Если в вы хотите
 . Сравнить выражение с результатом другого SELECT оператора
        выраж сравн {ALL | [ANY | SOME]} (SELECT-statement)
 . Определить, принадлежит ли выражение результатам     другого
   SELECT оператора.
        выраж [NOT] IN (SELECT-statement)
 . Выяснить, выбрал ли хоть что-нибудь другой SELECT оператор.
        [NOT] EXISTS  (SELECT-statement)
то применяйте условия с подзапросом.



---------------------------------------------------------------
SELECT  fio  FROM  kadry  WHERE zarplata=
   (SELECT MAX(zarplata) FROM kadry )
---------------------------------------------------------------
Здесь подзапрос возвращает единственное значение - максимальное
значение зарплаты. А внешний SELECT  оператор  находит  фамилии
обладателей оной.

---------------------------------------------------------------
SELECT  fio, shifr, organizaciq FROM zaqwki WHERE denxgi_rek is
not NULL and
 gorod in (SELECT gorod  FROM regiony WHERE region="Урал")
---------------------------------------------------------------
Здесь запрос выводит данные об руководителях, получивших финан-
сирование и работающих на Урале.

---------------------------------------------------------------
SELECT order_num,stock_num,manu_code, total_price FROM items  x
WHERE total_price >  (SELECT 2*MIN(total_price)
                        FROM items WHERE order_num=x.order_num)
---------------------------------------------------------------
Этот запрос (используя связанный подзапрос) выводит список всех
изделий, чья общая цена не менее чем в два раза превосходит ми-
нимальную цену изделий перечисленных в этом же ордере.

Вы можете соединять любое количество вышеперечисленных условий
вместе, используя логические операторы NOT, AND, OR.




Оператор  UNLOAD сбрасывает данные из таблицы в файл в печатном
представлении.  Каждая строка преобразуется в отдельную запись,
значения из столбцов разделяются символом "|".

После выполнения оператора
---------------------------------------------------------------
UNLOAD TO "kadry19.unl" SELECT * FROM kadry
---------------------------------------------------------------
в файле kadry19.unl можно будет обнаружить следующее:
---------------------------------------------------------------
5|5|туев|завхоз|100.0|31.12.1946|
4|6|петунин|кладовщик|80.0||
        . . .
---------------------------------------------------------------



Оператор LOAD выполняет обратную операцию - считывает строки из
файла и  вставляет  их  в  таблицу.  Естественно,  что  типы  и
количество  значений  в  строках  файла  должны соответствовать
столбцам таблицы.
---------------------------------------------------------------
LOAD FROM "kadry20.unl" INSERT INTO kadry
---------------------------------------------------------------






Выбрать  все  строки  (нет предложения WHERE) из таблицы kadry,
взять в них все столбцы (вместо перечисления столбцов стоит *),
оставить только различные строки (ключевое слово UNIQUE) и  по-
местить  результат  во временную таблицу (INTO TEMP) x, которая
будет при этом создана с такими же столбцами, что и у kadry.
---------------------------------------------------------------
SELECT UNIQUE * FROM kadry INTO TEMP x
---------------------------------------------------------------

Выбирать  можно из нескольких таблиц. При этом берутся все воз-
можные комбинации строк из первой таблицы со второй.  Предполо-
жим, что таблице tab1 6 строк а в tab2 - 7 строк. Результат ни-
жеприведенного  примера  -  таблица,  содержащая  три столбца и
7*6=42 строки.
---------------------------------------------------------------
SELECT tab1.a-tab2.b, tab1.a,  tab2.b  FROM  tab1,  tab2
---------------------------------------------------------------
Мы сейчас не будем уточнять, куда именно результирующая таблица
помещается. Но использовать ее можно по разному: ее  можно  пе-
регнать  (INTO  TEMP)  во временную таблицу, ее можно отдать на
обработку другому оператору (если выборку  осуществлял  подзап-
рос), для нее можно создать курсор ("буфер" с указателем на те-
кущую строку), а можно положить ее (INTO) в простую программную
переменную (если выбрано не более одной строки).

Выбранные строки можно упорядочить  по  возрастанию  (убыванию)
значения в столбце (столбцах)
---------------------------------------------------------------
SELECT a,b,c,d+e  FROM  tabl ORDER BY b,c
SELECT a,b,c,d+e  FROM  tabl ORDER BY 2,3
---------------------------------------------------------------
В ORDER BY предложении вместо имени столбца можно указывать его
порядковый номер в списке  выборки (select-list). Вышеприведен-
ные операторы эквивалентны.

Поместить значения из столбцов в переменные:  (Поскольку  lname
используется  и  как  имя переменной, и как имя столбца, то имя
столбца предваряется знаком (@)
---------------------------------------------------------------
SELECT customer_num, @lname,city INTO cnum,lname,town
FROM customer
---------------------------------------------------------------



К выбранным строкам можно применять агрегатные функции COUNT(*)
- количество,  MAX(column) и MIN(column) - максимальное и мини-
мальное значение в столбце, SUM(column) - сумма всех значений в
столбце, AVG(column) - среднее значение в столбце.

Поместить в переменную num количество строк в таблице orders, в
которых столбец customer_num равен 101:
---------------------------------------------------------------
SELECT COUNT(*)  INTO  num
FROM orders WHERE customer_num=101
---------------------------------------------------------------

Пример с использованием соединения  таблиц.  Находится  среднее
значение зарплаты превосходящей 300 (столбец zarplata принадле-
жит  одной из таблиц), при условии совпадения столбцов dolvnost
в двух таблицах.
---------------------------------------------------------------
SELECT AVG (zarplata) FROM table1,table2
WHERE   table1.dolvnost=table2.dolvnost and zarplata>300
---------------------------------------------------------------



Группировка используется для для "сплющивания" группы (строк) в
одну.

Результат  запроса  содержит  одну строку для каждого множества
строк, удовлетворяющих WHERE предложению и содержащих одно и то
же значение в указанном столбце.
---------------------------------------------------------------
SELECT dolvnostx, COUNT(*), AVG(zarplata) FROM kadry
GROUP BY dolvnostx
---------------------------------------------------------------
Получить  количество работающих и их среднюю зарплату по каждой
должности из штатного расписания.

---------------------------------------------------------------
SELECT dolvnostx, COUNT(*), AVG(zarplata) FROM kadry GROUP BY 1
---------------------------------------------------------------
Эквивалентная запись.

Предложение   HAVING   накладывает  дополнительные  условия  на
группу.
---------------------------------------------------------------
SELECT order_num, AVG(total_priece) FROM items
GROUP BY order_num HAVING COUNT(*) > 2
---------------------------------------------------------------
Этот  запрос  возвращает номера  ордеров   и  среднее  значение
total_price в заявках для всех ордеров, имеющих не  менее  двух
заявок.



Строки из таблицы, присоединенной внешним образом  (на  внешнее
соединение  указывает ключевое слово OUTER) будут выбираться не
смотря на то, удовлетворяют они условиям WHERE предложения  или
нет.  В некоторых случаях это полезно, когда у вас есть главная
таблица и есть вспомогательная, и данные из главной таблицы вам
нужно получить в любом случае. Пример внешнего соединения:
---------------------------------------------------------------
SELECT   company, order_num
        FROM customer c, OUTER  orders o
        WHERE  c.customer_num=o.customer_num
---------------------------------------------------------------
Запрос находит названия компаний и номера ордеров, которые  они
послали.  Если же компания ордеров не присылала, то ее название
все равно будет выбрано, а номер ордера в этой строке будет ра-
вен NULL. (А если бы мы запустили запрос без  параметра  OUTER,
то названия этих компаний вообще бы не попали в выборку.)




Операторы манипуляции данными - самая мощная составляющая SQL.

Следующий пример ликвидирует одинаковые строки в таблице kadry.
---------------------------------------------------------------
select unique * from kadry into temp kd
delete from kadry where 1=1
insert into kadry select * from kd
drop table kd
---------------------------------------------------------------

Следующий  пример  изменяет  информацию  в  строках по значению
ключа

   Tаблица   b  содержит  (kl int, pole char(20));
   причем все kl различны

   В таблице kadry  заменить   kadry.dolvnostx на  b.pole
   в строках где     kadry.tabnom=b.kl

---------------------------------------------------------------
SELECT b.kl,b.pole, nomerceh,dolvnostx,zarplata,datarovd
FROM  kadry, b  WHERE kadry.tabnom=b.kl into temp kd

DELETE FROM kadry WHERE tabnom in (SELECT kl FROM b)
INSERT INTO kadry SELECT * FROM kd
DROP TABLE kd
---------------------------------------------------------------

Ту же самую операцию можно проделать с помощью одного оператора
UPDATE, использующего подзапрос:
---------------------------------------------------------------
UPDATE kadry SET
dolvnostx=(select pole from b where kadry.tabnom=b.kl)
WHERE tabnom IN (select kl from b)
---------------------------------------------------------------


  Пример  изменяет информацию в строках по значению ключа
  при выполнении условий , наложенных на меняемые строки:

  Таблица agent           Таблица cia
+-----+---------+----+  +-----+       ---------+       ----+
|fio  | har     | cen|  |fio  | . . .  har     | . . .  cen|
|John |лентяй   |$300|  |John |       трудяга  |       $600|
|Piter|агент КГБ|    |  .  .  .
|Bob  |хороший  |$25 |  |Piter|       агент CIA|       $45 |
+-----+---------+----+  .  .  .
                        |Bob  |       плохой   |       $15 |
                        |Ronny|       плохой   |           |
                        .  .  .
                        +-----+       ---------+       ----+
В таблице  cia  хранятся сведения о сотрудниках. На основе пос-
ледних исследований была составлена таблица agent, с поправками
к содержанию cia.

Строчка будет подменяться, если за новую информацию о сотрудни-
ке в таблице agent заплачено больше, чем за хранящуюся в cia.
---------------------------------------------------------------
UPDATE cia SET
(har,cen)=( (SELECT har,cen FROM agent WHERE cia.fio=agent.fio) )
WHERE fio IN (SELECT fio  FROM agent) AND
 cen < (SELECT cen FROM agent WHERE cia.fio=agent.fio);

Популярность: 43, Last-modified: Tue, 25 Nov 1997 07:15:47 GmT