Программирование баз данных в Delphi

Автор работы: Пользователь скрыл имя, 26 Января 2013 в 14:13, лекция

Краткое описание

Программирование баз данных - очень большой и серьезный раздел самого что ни на есть практического программирования. На предыдущем курсе "Введение в программирование на Delphi" мы лишь коснулись этой темы, затронули даже не верхушку айсберга под названием Базы Данных, а только его макушку. Между тем, многие программисты большую часть своего времени тратят именно на проектирование баз данных и разработку приложений, работающих с ними. Это неудивительно - в настоящее время каждая государственная организация, каждая фирма или крупная корпорация имеют рабочие места с к

Вложенные файлы: 1 файл

Программирование баз данных в делфи.doc

— 2.17 Мб (Скачать файл)

Строки в примере написаны по правилам и рекомендациям языка SQL, то есть, операторы пишутся заглавными буквами, каждый оператор на отдельной строке, а в конце ставится точка с запятой. Однако рекомендации можно нарушать, а правила в Delphi более мягкие. Так, мы можем написать весь текст маленькими буквами, в одну строку, не ставить точку с запятой и не обращать внимания на регистр букв:

select * from lichdata

Запрос все равно будет выполнен. Однако лучше придерживаться рекомендаций и традиционного синтаксиса SQL, ведь этот язык имеет стандарты, и вы можете применять его не только при работе с Delphi. В других языках программирования или в клиент-серверных СУБД правила могут несколько отличаться, но в любом случае запрос, написанный в стандартном стиле, будет выполнен. Поэтому лучше сразу приучать себя к стандартному синтаксису. На данном курсе мы будем придерживаться рекомендаций SQL.

Что же написано у нас в этом запросе? Оператор SELECT означает "выделить", звездочка означает "все поля", оператор FROM означает "из…". Таким образом, запрос означает:

ВЫДЕЛИТЬ все поля ИЗ таблицы LichData

Но такой запрос ничем не отличается от применения табличных компонентов, а ведь мы можем создавать и  гораздо более сложные запросы! Предположим, нам нужно получить фамилию, имя и отчество сотрудника, а также город его проживания. Основные данные находятся в таблице LichData, а вот город находится в таблице Adres, связанной с таблицей LichData релятивной связью один-к-одному по полю "Ключ" таблицы LichData, и по полю "Сотрудник" таблицы Adres. В этом случае запрос будет выглядеть так:

SELECT Фамилия, Имя, Отчество, Город 

FROM LichData, Adres

WHERE Ключ = Сотрудник;

Как видите, в операторе SELECT поля перечисляются через запятую. Также через запятую перечисляются используемые таблицы в операторе FROM. А вот оператор WHERE указывает, что нужны только те записи, в которых значения поля "Ключ" и "Сотрудник" равны. Если бы мы не использовали оператор WHERE, то получили бы кучу недостоверных записей, где к каждой записи одной таблицы добавлялись бы все записи другой. Оператор WHERE позволил нам получить связные данные, в которых к одной записи первой таблицы добавляется соответствующая запись из другой таблицы. С этими и другими операторами мы подробней познакомимся на следующей лекции.

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

SELECT Фамилия, Имя, Телефон

FROM LichData, Telephones

WHERE Ключ = Сотрудник;

выдаст нам набор данных, в  котором фамилия и имя сотрудника будут дублироваться для каждого  номера его телефона.

Компонент-запрос может формировать  набор данных двух типов: изменяемый, в котором пользователь может  менять (редактировать, удалять или  добавлять) записи, и не изменяемый, предназначенный только для просмотра  данных или для составления отчетности. Возможность получения "живого" набора данных зависит от разных факторов - от применяемого оператора, от механизма доступа к данным, от используемой клиент-серверной СУБД. В данном примере мы используем оператор SELECT, работаем с локальной БД посредством механизма ADO. Если вы воспользуетесь навигатором, то убедитесь, что записи можно добавлять и удалять, а в сетке DBGrid их можно редактировать. Однако при редактировании данных, полученных более чем из одной таблицы, могут возникнуть трудности. Зато набор данных из одной таблицы можно спокойно изменять. Подробней с "живыми" и неизменяемыми наборами данных мы познакомимся позднее.

Компонент TQuery/TADOQuery может выполнять запросы двумя разными способами. Вначале в свойство SQL компонента помещается необходимый запрос. Это можно сделать программно, как в нашем SQL-мониторе, так и на этапе проектирования приложения. Дальнейшие действия зависят от того, какой запрос нам нужно выполнить. Если это запрос на получение набора данных, то есть, оператор SELECT, то достаточно просто открыть TQuery/TADOQuery методом Open, или присвоив True свойству Active. Если же запрос должен модифицировать данные, то есть, используются такие операторы, как INSERT, UPDATE, DELETE, то тогда запрос выполняется методом ExecSQL.

С работой компонента-запроса TQuery (TADOQuery) мы поработали на практике. Как и табличные компоненты, компонент-запрос произошел от родительского класса TDBDataSet. Унаследовав его свойства, методы и события, он имеет и собственные, отличительные черты. Так, например, запрос может быть изменяемым (живым), при котором пользователь может модифицировать записи набора данных, и не изменяемым, при котором данные доступны только для просмотра и составления отчетности. Наиболее важные свойства, методы и события, отличные от TDBDataSet, рассматриваются ниже.

Свойства компонента-запроса

Constrained - Свойство логического типа. Если свойство имеет значение True, то в изменяемом наборе данных на модифицируемые записи накладываются ограничения блока WHERE оператора SELECT (с операторами SQL-запросов вплотную познакомимся на следующей лекции).

DataSource - Указывает тот компонент TDataSource, который используется для формирования параметрического запроса.

Local - Свойство логического типа. Если свойство имеет значение True, это означает, что компонент-запрос работает с локальной или файл-серверной базой данных.

ParamCheck - Логическое свойство. При значении True список параметров автоматически обновляется при каждом программном изменении SQL-запроса.

Params - Свойство имеет тип TParams и содержит массив объектов-параметров этого типа. На этом типе данных следует остановиться подробнее:

Таблица 7.1. Свойства и методы типа TParams

Свойство 

Описание 

Items

Содержит массив параметров типа TParams и является свойством "по умолчанию". Индексация массива начинается с 0.

ParamValues()

Открывает доступ к значению параметра по его имени, указанному в скобках.

Count

Количество  параметров в массиве.

   

Метод

Описание

AddParam()

Добавляет параметр в массив параметров.

CreateParam()

Создает параметр и добавляет его к массиву.

FindParam()

Ищет параметр по его имени, указанному в скобках.

RemoveParam()

Удаляет параметр из массива.


Prepared - Свойство логического типа. Содержит значение True, если SQL-запрос был подготовлен методом Prepare.

RequestLive - Логическое свойство. Если компонент-запрос содержит изменяемый (живой) набор данных, то RequestLive содержит True.

RowsAffected - Свойство содержит количество записей, которые были удалены или отредактированы в наборе данных в результате выполнения SQL-запроса.

SQL - Свойство типа TStrings, то есть, набор строк. Содержит SQL-запрос, который выполняется, как только компонент-запрос становится активным (открывается). При изменении этого свойства, компонент-запрос автоматически закрывается, так что программисту требуется перевести свойство Active набора данных в True (или вызвать метод Open), чтобы запрос выполнился, и в НД появились запрошенные данные. Помещать строки запроса в свойство SQL можно как при проектировании, так и программно. В случае если программист создает запрос и открывает набор данных при проектировании приложения, он имеет возможность создать объекты-поля (см. предыдущую лекцию), и настраивать их свойства по своему усмотрению. При программном формировании НД такой возможности у него нет.

UniDirectional - Свойство логического типа. Содержит True, если курсор набора данных может перемещаться только вперед (типы курсоров см. в лекции №4). Это свойство используется, в основном, при работе с клиент-серверными СУБД, не поддерживающими курсоры, которые могут двигаться как вперед, так и назад.

Методы компонента-запроса

ExecSQL() - Выполняет модифицирующие запросы, то есть запросы на изменение, добавление или удаление записей, а также создание или удаление таблиц. В случае обычных запросов, выполненных с помощью оператора SELECT, используется метод Open, или присвоение значения True свойству Active набора данных.

ParamByName() - Метод дает доступ к значению параметра по его имени, указанному в скобках.

Prepare() - Метод используется для передачи SQL-запроса механизму доступа к данным, чтобы последний оптимизировал запрос. Оптимизация запроса происходит следующим образом: при выполнении любого запроса, механизм доступа к данным проверяет его синтаксис, что отнимает некоторое время. В случае многократного применения запроса, его можно выполнить методом Prepare(). При этом запрос компилируется и запоминается в буфере. При повторном выполнении этого запроса его синтаксис уже не проверяется.

UnPrepare() - Этот метод отменяет результаты действия метода Prepare(), и освобождает буфер от хранения компилированного запроса.

8. Лекция: Краткий курс языка запросов SQL: версия для печати и PDA  
На этой лекции вы познакомитесь с основными командами языка запросов SQL и научитесь формировать как простые, так и сложные запросы.

SQL (Structured Query Language) - Это Язык Структурированных Запросов. Он не такой богатый, как языки программирования высокого уровня. Тем не менее, это язык, без владения которым программисту, работающему с базами данных, не обойтись. Запросы, написанные на SQL, часто называют скриптами. Как вы уже знаете, эти скрипты можно непосредственно вводить в свойство SQL компонента-запроса в момент проектирования приложения, а можно значение этого свойства менять и в процессе прогона программы. Однако нередко используют и третий способ: программист создает набор скриптовых файлов, в процессе работы программа считывает из них SQL-инструкции в компоненты запросов и выполняет их. Это простые текстовые файлы, созданные в любом редакторе текстов, например, стандартном Блокноте Windows. Расширение может быть любым, но традиционно используется *.sql. Все это позволяет создавать гибкие программы. Если организации, использующей ваше приложение, в дальнейшем потребуются какие-то новые возможности, например, им нужно дополнительно создать еще один отчет, то применение скриптовых файлов избавит вас от необходимости переделывать программу, для этого достаточно будет написать скрипт.

В этой лекции мы разберем работу основных операторов SQL, после чего вы сможете создавать простые и сложные запросы и получать необходимые наборы данных. Тем, кто пожелает расширить свои познания SQL, рекомендую пройти соответствующий курс, посвященный этому языку, или прочитать книгу М. Грубера "Понимание SQL". Книга описывает стандартный синтаксис языка SQL и затрагивает все его возможности.

Команда SELECT

Команда SELECT является основой запроса. Большинство SQL-запросов начинаются с нее. Множество других команд вкладываются в блок SELECT. Полный синтаксис этой команды таков:

SELECT * | { [ DISTINCT | ALL] <value expression>.,..}

   FROM { <table name> [ <alias> ] }.,..

   [ WHERE <predicate>]

   [ GROUP BY { <column name> | <integer> }.,..]

   [ HAVING <predicate>]

   [ ORDER BY { <column name> | <integer> }.,..];

Здесь используются следующие элементы:

Таблица 8.1 . Элементы команды SELECT

Элемент

Описание 

<value expression>

Выражение, которое  производит значение. Оно может включать имена столбцов.

<table name>

Имя или синоним  таблицы или представления

<alias>

Временный синоним  для <table name>, определенный в этой таблице и используемый только в этой команде.

<predicate>

Условие, которое  может быть верным или неверным для  каждой строки или комбинации строк  таблицы в предложении FROM.

<column name>

Имя столбца  в таблице.

<integer>

Число с десятичной точкой. В этом случае, оно показывает <value expression> в предложении SELECT с помощью идентификации его местоположения в этом предложении.


В простейшем случае применение команды SELECT выглядит так:

SELECT *

FROM Table_Name;

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

SELECT Field1, Table1.Field2, Table2.Field2…

FROM Table1, Table2;

Команда FROM определяет имена таблиц, из которых осуществляется выборка данных. Если таблиц несколько, их имена разделяются запятыми. Иногда таблицы имеют длинные имена. В этом случае бывает выгодно использовать псевдонимы (alias) имен таблиц, указывая их через пробел после имени таблицы:

SELECT Field1, f.Field2, s.Field2

FROM Table1 f, Table2 s;

Команда WHERE

Команда WHERE позволяет использовать условие, которые может быть верным или нет для каждой записи БД. Если условие верное, то запись добавляется в набор данных, иначе отвергается. Давайте рассмотрим пример. Загрузите SQL-монитор из прошлой лекции. Предположим, нам нужно получить следующие данные на каждого сотрудника: Фамилия, Имя, Отдел, Должность. Пишем соответственный SQL-запрос:

SELECT Фамилия, Имя, Отдел,  Должность

FROM LichData, Doljnost;

Выполнив этот запрос, вы получите нечто непонятное. В полученном наборе данных всем сотрудникам подряд присваивается вначале первая должность, затем вторая, и так до конца. Другими словами, если у вас 10 сотрудников и 10 должностей, то вместо ожидаемых десяти записей вы получите 10 * 10 = 100 записей! Полученные данные называют недостоверными. Чтобы избежать этого, существует команда WHERE, которая позволяет задать условие выборки данных:

Информация о работе Программирование баз данных в Delphi