ООП IDE Borland C++ Builder Тема 3_3. Основы языка SQL и его использование в приложениях 1 Содержание • . 1 Оператор выбора Select 2. Операции с записями 3. Операции с таблицами 4. Операции с индексами 5. Основные свойства компонента Query 6. Основные методы и события компонента Query 2 Оператор выбора Select • SQL (Structured Query Language - язык структурированных запросов) позволяет формировать запросы к базам данных. • Запрос - это вопрос к базе данных, возвращающий запись или множество записей, удовлетворяющих вопросу. • C++Builder позволяет приложению при помощи запросов SQL использовать данные: Таблиц PARADOX и dBase - используется синтаксис локального SQL. Локального сервера InterBase - полностью поддерживается соответствующий синтаксис. Удаленных серверов SQL через драйверы SQL Links. • Язык SQL не чувствителен к регистру. Если в программе используется несколько операторов SQL, то в конце каждого оператора ставится точка с запятой ";" 3 Оператор выбора Select Отбор записей из таблицы • Оператор Select возвращает одно или множество значений, которые могут представлять собой значения указанных полей записей, удовлетворяющих указанному условию и упорядоченных по заданному критерию. • В качестве примера перенесем на форму компонент Query и установим его свойство DatabaseName равным dbP - базе данных Paradox. 4 Оператор выбора Select Отбор записей из таблицы • Поместим на форму компонент DataSource, свойство DataSet = Query1. • Поместим на форму компонент DBGrid, свойство DataSource = DataSource1. • Операторы SQL задаются в свойстве SQL компонента Query1, нужно установить значение свойства Active компонента Query1 в true. • Одна из форм оператора Select имеет следующий синтаксис: SELECT <список имен полей> FROM <таблица> WHERE <условие отбора> ORDER BY <список имен полей>; 5 Оператор выбора Select • • • • Отбор записей из таблицы Элементы оператора WHERE и ORDER BY не являются обязательными. WHERE определяет условие отбора записей: отбираются только те, в которых условие выполняется. ORDER BY определяет упорядочивание возвращаемых записей. <таблица> - это таблица базы данных, из которой осуществляется отбор, например, Pers. 6 Оператор выбора Select • • • • • Отбор записей из таблицы После ключевого слова Select указываются имена полей таблицы, которые будут возвращены. Имена полей разделяются запятыми. Например, оператор SELECT Fam, Nam, Par, Year_b FROM Pers указывает, что следует вернуть поля Fam, Nam, Par и Year_b из таблицы Pers. Запишем его в свойстве SQL компонента Query1, установим значение свойства Active в true и посмотрим результаты. Если указать вместо списка полей "*" - это значит, что требуется вернуть все поля. SELECT * FROM Pers означает выбор всех полей. 7 Оператор выбора Select Отбор записей из таблицы • В списке могут быть и арифметические выражения с помощью операций +, -, *, /. • После выражения может записываться псевдоним выражения в форме: AS <псевдоним>. • В качестве псевдонима может фигурировать любой идентификатор, на который потом можно при необходимости ссылаться. • Он будет при отображении результатов фигурировать в заголовке таблицы. • Такими простыми средствами создаются аналоги вычисляемых полей. Пример использования выражения: SELECT Fam, Nam, (2000-Year_b) AS Age FROM Pers • Этот оператор создает поле Age, вычисляемое по формуле (2000-Year_b). 8 Оператор выбора Select Отбор записей из таблицы • Условие отбора, задаваемые после ключевого слова WHERE определяет критерий, по которому отбираются записи. • Оператор Select отбирает только те записи, в которых заданное условие истинно. • Условие может включать имена полей, константы, логические выражения, содержащие арифметические операции, логические операции and, or, not и операции отношения: 9 Оператор выбора Select Отбор записей из таблицы = равно > больше >= больше или равно < меньше <= меньше или равно != не равно Like наличие заданной последовательности символов between ... and диапазон значений in соответствие элементу множества 10 Оператор выбора Select • Первые шесть операций очевидны. • SELECT Fam FROM Pers WHERE Pol=false and Year_b > 1960 отберет записи, относящиеся к женщинам, родившимся после 1960 года. • Операция Like имеет синтаксис: <поле> LIKE <последовательность символов> • Like применима к полям типа строк и возвращает true, если в строке встретился фрагмент, заданный в операции как <последовательность символов>. • Заданным символам может предшествовать и их может завершать символ процента "% ", который означает - любое количество любых символов. 11 Оператор выбора Select • Если символ процента не указан, то заданная последовательность символов должна соответствовать только целому слову. Например, условие Fam LIKE 'A%' • означает, что будут отобраны все записи, в которых фамилия начинается с заглавной русской буквы "А" (операция Like различает строчные и прописные символы). • Условию Fam LIKE 'Иванов%' • будут удовлетворять фамилии «Иванов» и «Иванова», а условию Fam LIKE ' %ван%' кроме этих фамилий будет удовлетворять, например, фамилия «Иванников». 12 Оператор выбора Select Операция between ... and имеет синтаксис: <поле> between <значение> and <значение> • и задает для указанного поля диапазон отбираемых значений. Например, оператор SELECT Fam, Year_b FROM Pers WHERE Year_b BETWEEN 1960 AND 1970 • отберет записи сотрудников в заданном диапазоне возраста (включая граничные значения 1960 и 1970). 13 Оператор выбора Select Операция in имеет синтаксис: <поле> in (<множество>) • отбирает записи, в которых значение указанного поля является одним из элементов указанного множества. Например, оператор SELECT Fam, Year_b FROM Pers WHERE Fam IN('Иванов','Петров','Сидоров') • отберет записи сотрудников с заданными фамилиями, а оператор SELECT Fam, Year_b FROM pers WHERE Year_b IN (1950,1960) • отберет записи сотрудников указанных годов рождения. 14 Оператор выбора Select • Ключевое слово ORDER BY определяет упорядочивание (сортировку) записей. • После ORDER BY следует список полей, определяющих сортировку. • Можно указывать только поля, фигурирующие в списке отобранных (в списке после ключевого слова SELECT). • Причем эти поля могут быть и вычисляемыми. • Если в списке сортировки указано только одно поле, то сортировка производится по умолчанию в порядке возрастания значений этого поля. Например, оператор SELECT Dep, Fam, Year_b FROM Pers ORDER BY Year_b • задает упорядочивание возвращаемых значений по нарастанию года рождения. 15 Оператор выбора Select • Если желательно располагать результаты по убыванию значений, то после имени поля добавляется ключевое слово DESC: SELECT Dep, Fam, Year_b FROM Pers ORDER BY Year_b DESC • Если в списке после ORDER BY перечисляется несколько полей, то первое из них - главное и сортировка проводится прежде всего по значениям этого поля. • Записи, имеющие одинаковое значение первого поля упорядочиваются по значениям второго поля и т.д. 16 Оператор выбора Select Например, оператор SELECT Dep, Fam, Year_b FROM Pers ORDER BY Dep, Fam • сортирует записи прежде всего по отделам (значениям поля Dep), а внутри каждого отдела - по алфавиту. Оператор SELECT Dep, Fam, Year_b, Pol FROM Pers ORDER BY Dep, Pol, Fam • сортирует записи по отделам, полу и алфавиту. 17 Оператор выбора Select Совокупные характеристики • Select позволяет возвращать также и некоторые совокупные (агрегированные) характеристики, подсчитанные по всем или по указанным записям таблицы. • Одна из функций, возвращающих такие совокупные характеристики, соunt(<условие>) - количество записей в таблице, удовлетворяющих заданным условиям. Например, оператор SELECT count(*) FROM Pers подсчитает полное количество записей в таблице Pers. • А оператор SELECT count (*) FROM Pers WHERE Dep='Цex 1' • выдаст число записей сотрудников цеха 1. 18 Оператор выбора Select Совокупные характеристики • Ключевое слово DISTINCT (уникальный) позволяет выбор числа неповторяющихся значений в указанном поле. Например, оператор SELECT count(DISTINCT Dep) FROM Pers • вернет число различных подразделений, упомянутых в поле Dep таблицы Pers. • Функции min(<поле>), mах(<поле>), avg(<поле>), sum(<поле>) возвращают соответственно минимальное, максимальное, среднее и суммарное значения указанного поля. 19 Оператор выбора Select Совокупные характеристики Например, оператор SELECT min(Year_b), max(Year_b), avg(Year_b) FROM Pers • вернет минимальное, максимальное и среднее значение года рождения. Оператор SELECT min(2007-Year_b), max (2007Year_b), avg(2007-Year_b) FROM Pers WHERE Dep='Бухгалтерия' • выдаст вам аналогичные данные, но относящиеся к возрасту сотрудников бухгалтерии. 20 Оператор выбора Select Совокупные характеристики • В операторе Select можно указывать не только суммарные характеристики, но и любые выражения от них, например, оператор SELECT 2007-(min(Year_b)+max (Year_b))/2 FROM Pers WHERE Dep='Бухгалтерия' • выдаст моду (среднее между максимальным и минимальным значениями) возраста сотрудников бухгалтерии. • При использовании суммарных характеристик надо учитывать, что в списке возвращаемых значений после ключевого слова SELECT могут фигурировать или поля, или совокупные характеристики, но не могут фигурировать и те, и другие 21 Оператор выбора Select • Смешение в одном операторе полей и совокупных характеристик возможно, если использовать группировку записей, задаваемую ключевыми словами GROUP BY. • После этих ключевых слов перечисляются все поля, входящие в список SELECT. • В этом случае смысл совокупных характеристик изменяется: они проводят вычисления не по всем записям таблицы, а по тем, которые соответствуют одинаковым значениям указанных полей. • Например, оператор SELECT Dep, count(*) FROM Pers GROUP BY Dep вернет таблицу, в которой будет 2 столбца: столбец с названиями отделов, и столбец, в котором будет отображено число сотрудников в каждом отделе. 22 Оператор выбора Select Вложенные запросы • Результаты, возвращаемые оператором Select, можно использовать в другом операторе Select. • Это относится и к операторам, возвращающим совокупные характеристики, и к операторам, возвращающим множество значений. • Например, узнать фамилию самого молодого сотрудника можно с помощью вложенных запросов: SELECT Fam,Year_b FROM Pers WHERE Year_b=(SELECT max(Year_b) FROM Pers) • Здесь оператор SELECT max(Year_b) FROM Pers возвращает максимальный год рождения, который используется в элементе WHERE основного оператора Select для поиска сотрудника, чей год рождения совпадает с максимальным. 23 Оператор выбора Select Вложенные запросы • Вложенные запросы могут обращаться к разным таблицам. • Пусть, например, мы имеем две аналогичных по структуре таблицы Pers и Pers1, относящиеся к разным организациям, и хотим в таблице Pers найти всех однофамильцев сотрудников другой организации. • Чтобы проверить работу с несколькими таблицами, нужнооткрыть в Database Desktop таблицу Pers, выполнить команду Table | Restructure и кнопкой Save as сохранить таблицу под именем Pers1. 24 Оператор выбора Select Вложенные запросы • Например, оператор определяет всех однофамильцев в этих двух таблицах. SELECT * FROM Pers WHERE Fam IN (SELECT Fam FROM Pers1) • Вложенный оператор Select Fam from Pers1 возвращает множество фамилий из таблицы Pers1, а конструкция WHERE основного оператора Select отбирает из фамилий в таблице Pers те, которые имеются в множестве фамилий из Pers1. • При работе в условии WHERE с множествами записей можно использовать ключевые слова: All и Any. • All - что условие выполняется для всех записей; • Any - хотя бы для одной записи. 25 Оператор выбора Select Вложенные запросы Например, оператор SELECT * FROM Pers WHERE Year_b >= ALL (SELECT Year_b FROM Pers1) • ищет сотрудников в Pers, которые не старше любого сотрудника в Pers1. • Если в этом операторе заменить Pers1 на Pers, то получим список самых молодых сотрудников организации, который мы получали ранее другим способом. А оператор SELECT * FROM Pers WHERE Year_b > ANY (SELECT Year_b FROM Pers1) • ищет сотрудников в Pers, которые моложе хотя бы одного сотрудника в Pers1. 26 Оператор выбора Select Объединения таблиц • В запросе можно объединить данные двух или более таблиц. • Пусть, нужно получить список сотрудников всех производственных подразделений. • В таблице Pers есть список сотрудников с указанием в поле Dep подразделений. • А в таблице Dep есть список всех подразделений в поле Dep и характеристику каждого подразделения в поле Prosv. • Тогда получить список сотрудников всех подразделений можно оператором: SELECT Pers.* FROM Pers, Dep WHERE (Pers.Dep=Dep.Dep) AND (Dep.Proisv=true) 27 Оператор выбора Select • • • • • • Объединения таблиц Обращение сразу к двум таблицам Pers и Dep, которые перечислены после ключевого слова FROM. Поэтому каждое имя поля предваряется ссылкой на таблицу, к которой оно относится. Надо только для полей, имя которых повторяется в разных таблицах (поле Dep). Перед полем Proisv ссылку на таблицу можно опустить. В конструкции WHERE условие Pers.Dep=Dep.Dep ищет запись в таблице Dep, в которой поле Dep совпадает с полем Dep текущей записи таблицы Pers. А условие Dep.Proisv=true отбирает те записи, в которых в таблице Dep найденному подразделению 28 соответствует поле Proisv = true. Оператор выбора Select Объединения таблиц • В операторах, работающих с несколькими таблицами, обычно каждой таблице дается псевдоним, сокращающий ссылки на таблицы. • Псевдоним таблицы может записываться в списке таблиц после слова FROM, отделяясь от имени таблицы пробелом. • Например, приведенный выше оператор может быть переписан следующим образом; SELECT P.* FROM Pers P, Dep D WHERE (P.Dep=D.Dep)AND(D.Proisv=true) • В этом примере таблице Pers дан псевдоним Р, а таблице Dep - D. Эти псевдонимы действуют только в данном операторе и не имеют никакого отношения к псевдонимам баз данных. 29 • . Оператор выбора Select Объединения таблиц • Возможно самообъединение таблицы - в этом случае одной таблице даются два псевдонима. • Пусть нужно найти всех ровесников в организации. Это можно сделать оператором SELECT p1.fam, p2.fam, p1.Year_b FROM Pers p1, Pers p2 WHERE (p1.year_b = p2.year_b) AND (p1.fam!= p2.fam) and (p1.Fam < p2.Fam) • Для таблицы Pers использовали два псевдонима: p1 и р2. В конструкции WHERE ищутся в этих якобы разных таблицах записи с одинаковым годом рождения. • Второе условие p1.fam!= p2.fam нужно, чтобы сотрудник не отображался в результатах как ровесник сам себя. 30 Оператор выбора Select • • • • Объединения таблиц Чтобы исключить дублирование добавлено условие – p1.Fam < p2.Fam: Возможны и объединений, которые выдают записи независимо от того, есть ли соответствующее поле во второй таблице - внешние объединения (outer join). Их три типа: левое, правое и полное. Левое объединение (обозначается ключевыми словами LEFT OUTER JOIN ... ON) включает в результат все записи первой таблицы, даже те, для которых не имеется соответствия во второй. Правое объединение (обозначается ключевыми словами RIGHT OUTER JOIN ... ON) включает в результат все записи второй таблицы, даже если им нет соответствия в записях первой. 31 Оператор выбора Select • • • • • Объединения таблиц Полное объединение (FULL OUTER JOIN ... ON) включает в результат объединение записей обеих таблиц, независимо от их соответствия. Пусть имеется таблица сотрудников некоей компании Pers и таблица Chef, в которой занесены данные на членов совета директоров этой компании. В число членов совета входят и сотрудники компании, и посторонние лица. Для определенности положим, что в таблице Pers имеются записи на сотрудников «Иванов» и «Петров», причем Петров является членом совета, а Иванов - нет. В таблице Chef имеются записи на членов совета «Петров» и «Сидоров», причем Сидоров - не сотрудник компании. 32 Оператор выбора Select Объединения таблиц Тогда оператор SELECT * FROM Pers LEFT OUTER JOIN Chef ON Pers.Fam = Chef.Fam выдаст результат вида: Поля таблицы Pers Иванов Петров Поля таблицы Chef Петров • Оператор задал левое объединение таблицы Pers (она указана после ключевого слова FROM) с таблицей Chef (она указана после ключевых слов LEFT OUTER JOIN). • Условие объединения указано после ключевого слова ON и заключается в совпадении фамилий. 33 Оператор выбора Select • • • • Объединения таблиц Результат включает все поля и таблицы Pers, и таблицы Chef. Число строк соответствует числу записей таблицы Pers. В строках, относящихся к записям, для которых в Chef не нашлось соответствие, поля таблицы Chef остаются пустые. Оператор правого объединения SELECT * FROM Pers RIGHT OUTER JOIN Chef ON Pers.Fam = Chef.Fam выдаст результат вида: Поля таблицы Pers Петров Поля таблицы Chef Петров Сидоров 34 Оператор выбора Select Объединения таблиц • Число строк соответствует числу записей таблицы Chef. • В строках, для которых в Pers не нашлось соответствие, поля таблицы Pers остаются пустые Оператор полного объединения • SELECT * FROM Pers FULL OUTER JOIN Chef ON Pers.Fam =Chef.Fam выдаст результат вида: Поля таблицы Pers Поля таблицы Chef Иванов Петров Петров Сидоров • В нем к строкам, относящимся к таблице Pers, добавлены строки, относящиеся к таблице Chef, для которых не нашлось соответствия в таблице Pers.35 Оператор выбора Select SQL операторы манипулирования с записями • Вставка новой записи в таблицу осуществляется оператором Insert, который может иметь вид: INSERT INTO <имя таблицы> (<список полей>) VALUES (<список значений:») • В списке перечисляются только те поля, значения которых известны, остальные могут опускаться. • Для пропущенных полей значения берутся по умолчанию или поля остаются пустыми. Например: INSERT INTO Pers (Fam, Nam, Par, Pol) VALUES ('Иванов', 'Андрей', 'Андреевич', true) • В этом примере не указан год рождения. • Он подставится по умолчанию и в дальнейшем может быть уточнен. 36 Оператор выбора Select SQL операторы манипулирования с записями • Другая форма оператора Insert использует множество значений, возвращаемых оператором Select. • Этот оператор может выбирать записи из какой-то другой таблицы и вставлять их в данную. Синтаксис этой формы Insert : INSERT INTO <имя таблицы> <оператор Select> • Пусть имеется таблица Old_Pers пожилых людей организации и нужно заполнить ее записями из таблицы Pers. Это можно сделать одним оператором: INSERT INTO O1d_Pers SELECT * FROM Pers WHERE Year_b < 1939 • Таблица Old_Pers сразу заполнится множеством 37 соответствующих записей из Pers. Оператор выбора Select SQL операторы манипулирования с записями • Приведенный оператор Insert можно использовать для копирования данных одной таблицы в другую, причем эти таблицы могут быть созданы разными СУБД. • Редактирование записей осуществляется оператором Update: UPDATE <имя табл.> SET <список вида <поле>=<выражение>> WHERE <условие> • Наличие условия позволяет редактировать не только одну запись, но сразу множество их. • Например, если решили слить «Цех 1» и «Цех 2» в один «Цех 1», то исправление всех записей в таблице можно сделать одним оператором: UPDATE Pers SET Dep='Цех 1' WHERE Dep='Цех 2' 38 Оператор выбора Select SQL операторы манипулирования с записями • Удаление записей осуществляется оператором Delete: DELETE FROM <имя таблицы> WHERE <условие> • Наличие в операторе условия позволяет удалять не только одну, но сразу множество записей. • Например, если при реорганизации предприятия подразделение «Цех 1» ликвидировали, то удалить из таблицы все соответствующие записи можно оператором: DELETE FROM Pers WHERE Dep = 'Цех 1' 39 Оператор выбора Select SQL операторы манипулирования таблицами • Создание новой таблицы осуществляется оператором Create Table: CREATE TABLE <имя таблицы> (<список вида <имя поля> <тип>(<размер>)>) • Размер указывается только для полей строковых и некоторых других типов. • После объявления некоторых полей могут включаться слова PRIMARY KEY, что указывает на то, что данное поле входит в первичный ключ. • Кроме того, после объявления некоторых полей можно вставлять слова NOT NULL, означающие, что значение этого поля обязательно должно быть задано в каждой записи. 40 Оператор выбора Select SQL операторы манипулирования таблицами Например: • CREATE TABLE Person (Fam char(15) NOT NULL PRIMARY KEY, Nam char(15) NOT NULL PRIMARY KEY, Par char(15) NOT NULL PRIMARY KEY, Year_b integer ) • Приведенная форма оператора Create Table простейшая. • Более сложные формы позволяют задавать в таблице вычисляемые поля, значения по умолчанию, ограничения значений, связывать разные таблицы по ключам и многое другое. 41 Оператор выбора Select SQL операторы манипулирования таблицами • Удаление таблицы осуществляется оператором Drop Table: DROP TABLE <имя таблицы> • Удаление таблицы полностью уничтожает таблицу. • Модификация структуры существующей таблицы осуществляется оператором Alter Table: ALTER TABLE <имя таблицы> <действие> <имя поля> <тип данных> ... • В этом операторе <действие> может принимать значения ADD - добавить новое поле, или DROP удалить существующее поле. • Если поле добавляется, то для него надо указывать <тип данных>, ели поле удаляется, то тип данных не указывается ALTER TABLE Pers DROP Year_b, ADD Age integer 42 Оператор выбора Select SQL операторы манипулирования индексами • Индексы существенно ускоряют процесс поиска и упорядочивания записей таблицы. • Создание нового индекса осуществляется оператором Create Index: CREATE INDEX <имя индекса> ON <имя таблицы > <список полей> • Например: CREATE INDEX depyear ON Pers Dep, Year_b • Удаление существующего индекса осуществляется оператором Drop Index: DROP INDEX <имя таблицы >.<имя индекса> • Например: DROP Index Pers.depyear 43 Оператор выбора Select SQL операторы манипулирования индексами • Если таблица многократно изменяется и в нее вносится много новых записей: индексы могут оказаться разбалансированы их эффективность при выполнении запросов уменьшается. • В этом случае полезно проводить повторное создание и балансировку индекса последовательным применением операторов деактивации и активации: ALTER INDEX <имя индекса> DEACTIVATE ALTER INDEX <имя индекса> ACTIVATE • 44 Основные свойства компонент Query. • Компонент Query позволяет работать с таблицами, используя операторы SQL. • Большинство свойств и методов Query совпадают с Table. • Дополнительные преимущества Query возможность формировать запросы на языке SQL. • Исходя из возможностей Table и Query, можно заключить, что в серверных приложениях целесообразнее использовать Query, а при работе с локальными базами данных компонент Table. 45 Основные свойства компонент Query. • • • • • Пример использования Query. Поместим на форму компоненты Query, DataSource, DBGrid. В свойстве DataSet компонента DataSource1 зададим Query1, а в свойстве DataSource компонента DBGrid1 зададим DataSource1. Создали обычную цепочку: набор данных (Query1), источник данных (DataSource1), компонент визуализации и управления данными (DBGrid1). Основное свойство Query - SQL типа Tstrings список строк, содержащих запросы SQL. В процессе проектирования обычно необходимо сформировать в этом свойстве некоторый запрос SQL, который показал бы, с какой таблицей или таблицами будет проводиться работа. 46 Основные свойства компонент Query. • • • • Пример использования Query. Во время выполнения приложения свойство SQL может формироваться программно методами, обычными для класса TStrings: Clear - очистка, Add - добавление строки и т.д. Настройку компонента Query в процессе проектирования можно производить вручную Прежде, чем приступать к настройке, в свойстве DataBaseName компонента Query надо задать базу данных, с которой будет осуществляться связь из выпадающего списка псевдонимов, или указанием полного пути к каталогу или файлу. Свойства TableName нет, т.к. таблица, с которой ведется работа, в Query будет указываться в запросах SQL. 47 Основные свойства компонент Query. • • • • • Пример использования Query. Поэтому, прежде всего надо занести в свойство SQL запрос, содержащий имя таблицы, с которой нужно работать. Предупреждение .Прежде, чем начинать детальную настройку компонента Query, надо сформировать в свойстве SQL запрос, в котором указывается таблица и перечисляются параметры, если они используются в приложении. Пока токай запрос в SQL отсутствует, дальнейшая настройке Query невозможно. Запрос, заносимый в SQL в начале проектирования, носит чисто служебный характер. В дальнейшем можно его программно заменить на любой другой запрос. 48 Основные свойства компонент Query. • • • • • Пример использования Query. Запрос, заносимый в SQL в начале проектирования, может иметь, например, следующий вид: Select * from pers После этого система поймет, с какой таблицей будет проводиться работа, и можно будет настроить поля в Query. Если работа будет проводиться с несколькими таблицами, нужно их указать в запросе. Например: Select * from pers, dep После того как соответствующий запрос написан, можно установить свойстве Active компонента Query в true. Если все выполнено правильно, то в компоненте DBGrid1 отобразится информация из запрошенных таблиц. 49 Основные свойства компонент Query. • • • • • • Пример использования Query. Приложение предоставляет возможность просматривать записи, но, к сожалению, не позволяет их редактировать. Это связано с тем, что запрос Select возвращает таблицу только для чтения. В таком простом приложении это легко исправить. Достаточно установить в компоненте Query1 свойство RequestLive в true. Это позволяет возвращать как результат запроса изменяемый, «живой» набор данных, вместо таблицы только для чтения. Точнее, установка RequestLive в true делает попытку вернуть «живой» набор данных. 50 Основные свойства компонент Query. Пример использования Query. • Успешной эта попытка будет только при соблюдении ряда условий, в частности: набор данных формируется обращением только к одной таблице набор данных не упорядочен (в запросе не используется ORDER BY) в наборе данных не используются совокупные характеристики типа Sum, Count и др. набор данных не кэшируется (свойство CashedUpdates равно false) • В примере все эти условия соблюдаются, поэтому установив RequestLive в true можно редактировать данные, удалять записи, вставлять новые записи. 51 Основные свойства компонент Query. • Для управления отображением данных используется Редактор Полей (Field Editor) - вызывается двойным щелчком на Query. В нем можно: • добавить имена получаемых полей (щелчок правой кнопкой мыши и выбор раздела меню Add), • задать заголовки полей, отличающиеся от их имен, • сделать какие-то поля невидимыми (Visible), • не редактируемыми (Readonly), • в логических полях можно задать высвечиваемые слова (да;нет), • задать формат высвечивания чисел, • создать вычисляемые поля, поля просмотра, • задать диапазоны значений и многое другое. 52 Основные свойства компонент Query. • • • • • Динамические запросы и параметры Query Все рассмотренные запросы SQL - это так называемые статические запросы. В них фиксировано все: имена таблиц, поля, константы в выражениях и т.п. SQL допускает также и динамические запросы, использующие параметры. Параметры можно применять вместо имен таблиц, имен полей и их значений. Значения этих параметров передаются извне и тем самым, не изменяя текст самого запроса, можно менять возвращаемый им результат. 53 Основные свойства компонент Query. Динамические запросы и параметры Query • Параметры задаются в запросе с двоеточием, предшествующим имени параметра: • :<имя параметра> • Например, можно записать в запросе Select элемент WHERE в виде: WHERE Year_b <= :PYear • Здесь сравнивается год рождения не с какой-то константой, а со значением параметра PYear. • Введем в свойство SQL компонента Query запрос, содержащий параметры, например: Select * from pers where (year_b>:PYear) and (dep=:Dep) 54 Основные свойства компонент Query. Динамические запросы и параметры Query • в Инспекторе Объектов при выборе свойства Params, откроется е окно со списком объектов указанных в запросе параметров PYear и Dep. В этом списке можно выделять по очереди параметры и в Инспекторе Объектов устанавливать их свойства. Это свойства: DataType Name ParamType тип данных параметра (int, string и т.п.) имя параметра тип параметра (используется при обращении к хранимым на сервере процедурам Value значение параметра по умолчанию Type - подсвойство тип значения по умолчанию Value 55 Основные свойства компонент Query. • • • • Динамические запросы и параметры Query После установки свойства всех параметров, можно использовать их при программировании приложения. Программный доступ к параметрам во время выполнения приложения осуществляется аналогично доступу к полям набора данных. Свойство Params является указателем на массив параметров типа TParam, к элементам которого можно обращаться по индексу через его свойство Items[Word Index]. Последовательность, в которой располагаются параметры в массиве, определяется последовательностью их упоминания в запросе SQL. 56 Динамические запросы и параметры Query. • Значения параметров, как и значения полей, определяются такими свойствами объектов-па оператор for (int i = 0; i < Query1->Params->Count; i++) if (Query1->Params->Items[i]->IsNull && Query1>Params->Items[i]->DataType == ftInteger) Query1->Params->Items[i]->AsInteger = -1; • задаст значение «-1» всем целым параметрам, которым до этого не было присвоено значение. • Использовано свойство Count - число параметров, свойство IsNull, равное true, если параметру не задано никакое значение, свойство DataType, указывающее тип параметра, и свойство AsInteger, дающее доступ к значению параметра как к целому числураметров, как Value, AsString, Aslnteger и т.п. 57 Динамические запросы и параметры Query. операторы Query1->Params->Items[0]->AsInteger = 1950; Query1->Params->Items[1]->AsString = "Бухгалтерия"; • задают значения первому (индекс 0) и второму (индекс 1) параметрам компонента Query1, в свойстве SQL которого записан приведенный ранее оператор Select с параметрами :PYear и :Dep. • Поскольку в этом операторе параметр :PYear упоминается первым, го его индекс равен 0. • У Params есть еще свойство - ParamValues. Оно представляет собой массив значений параметров типа Variant. • В качестве индекса в это свойство передается имя параметра или несколько имен, разделяемых точками с запятой 58 Динамические запросы и параметры Query. • • • • • • • операторы Query1->Params->ParamValues["PYear"] = 1950; Query1->Params->ParamValues["Dep"] = "Бухгалтерия"; задают те же значения параметрам, что и приведенные выше. Преимуществом является то, что при записи этих операторов не надо помнить индексы параметров. Другим преимуществом свойства ParamValues является возможность задать значения сразу нескольким параметрам. Variant par[] = {1950,"Бухгалтерия"); Query1->Params->ParamValues["PYear;Dep"] = VarArrayOf(par,1); 59 Динамические запросы и параметры Query. • Другой способ обращения к параметрам использование метода ParamByName компонента Query. операторы • Query1->ParamByName("PYear")->AsInteger = 1950; • Query1->ParamByName("Dep")->AsString = "Бухгалтерия"; • задают параметрам с именами PYear и Dep те же значения. • Следует оговориться, что задание нового значения параметру само по себе еще не обеспечивает влияния на возвращаемый из запроса результат. • Надо повторно выполнить данный запрос, чтобы ощутить изменения. 60 Связывание таблиц • Большинство свойств Query аналогичны свойствам Table. • Объекты полей создаются автоматически для тех полей, которые перечислены в операторе SQL. • Программный доступ к этим полям осуществляется так же с помощью свойства Fields (например, Query1-> Fields[0]) или методом FieldByName (например, Query1->FieldByName("Dep")). • Можно также создавать объекты полей с помощью Редактора Полей, вызываемого двойным щелчком на Query или из меню, всплывающего при щелчке на Query правой кнопкой мыши. • В этом случае доступ к объекту поля можно осуществлять также и по его имени (например, Query1Dep). 61 Связывание таблиц • При использовании для Query Редактора Полей надо добавлять в нем все поля, перечисленные в операторе SQL • Предупреждение. Доступ к полям по имени возможен только в случае, если объекты полей были созданы с помощью Редактора Полей. • Для доступа к значениям полей используются те же их свойства Value, AsString, Aslnteger. • Точно так же, как в Table, можно осуществлять навигацию по набору данных, устанавливать фильтры, ограничивать вводимые значения полей, кэшировать изменения. • Из свойств, отличных от Table, остановимся на свойстве DataSource. Это свойство позволяет строить приложения, содержащие связанные друг с 62 другом таблицы. Связывание таблиц Рассмотрим пример. • Построить приложение, включающее в себя таблицу Dep, содержащую список отделов (в поле Dep) и их характеристику, в качестве головной таблицы и таблицу персонала Pers, содержащую в поле Dep имя отдела, в котором работает каждый сотрудник. • Нужно, чтобы при выборе записи в таблице Dep в таблице Pers отбирались записи, относящиеся к выбранному отделу. • Поместим на форму: компоненты Query1, DataSource1, DBGrid1 соединим их обычной цепочкой: в DBGrid1 свойство DataSource = DataSource1, а в DataSource1 свойство DataSet = Query1. 63 Связывание таблиц • • • • • Рассмотрим пример. Компонент Query1 настроим на таблицу Dep установим свойство DatabaseName (например, dbP), а в свойстве SQL напишем оператор Select * from Dep Установим свойство Active в true и в DBGrid1 должно отобразиться содержимое таблицы Dep. Создадим другую аналогичную цепочку, перенеся на форму компоненты Query2, DataSource2, DBGrid2, и свяжем ее с таблицей Pers запросом Select * from Pers в компоненте Query2. Установим свойство Active компонента Query2 в true и в DBGrid2 отобразится содержимое таблицы Pers. 64 Связывание таблиц • • • • • • Рассмотрим пример. Пока таблицы независимы. Теперь нужно связать эти таблицы. Изменим текст запроса в свойстве SQL вспомогательного компонента набора данных Query2 на Select * from Pers where (Dep=:Dep) В этом запросе указано условие отбора: значение поля Dep должно быть равно параметру :Dep. Далее в свойстве DataSource компонента Query2 надо сослаться на DataSource1 - источник данных, связанный с таблицей Dep. Это скажет приложению, что оно должно взять значения параметра :Dep из текущей записи этого источника данных. 65 Связывание таблиц • А поскольку имя параметра совпадает с именем поля в источнике данных, то в качестве значения параметра будет взято текущее значение этого поля. • Таким образом, вспомогательная таблица, запрашиваемая в Query2, оказывается связанной с головной таблицей, запрашиваемой в Query1. • После изменения содержимого свойства SQL свойство Active компонента Query2 сбросится в false. • Нужно установить его в true и запустить приложение. • Увидим, что при перемещении по первой таблице во второй отображаются только те записи, которые относятся к отделу, указанному в 66 текущей записи первой таблицы. Основные методы компонента Query • К основным методам Query можно отнести методы открытия и закрытия соединения с базой данных. • Метод Close закрывает соединение с базой данных, переводя свойство Active в false - метод надо выполнять перед изменением каких-то свойств, влияющих на выполнение запроса или на отображение данных. • Метод Open открывает соединение с базой данных и выполняет запрос, содержащийся в свойстве SQL - применим только в случае, если запрос сводится к оператору Select. • Если же запрос содержит другой оператор, например, Update или Insert, то при выполнении Open будет генерироваться исключение EDatabaseError. 67 Основные методы компонента Query • В некоторых случаях приложению требуется получить список имен полей таблицы, связанной с Query. • Это может быть сделано методом GetFieldNames, который загружает список имен полей в любую переменную типа TStrings, передаваемую в него в качестве аргумента. Например, оператор • Query1->GetFieldNames(ComboBox1->Items) ; • загружает в выпадающий список ComboBox1 имена полей таблицы, связанной с Query1. • В дальнейшем будет приведен пример использования этого метода. 68