понедельник, 1 апреля 2013 г.

Lazarus. Простой код запроса к Firebird DB для Grid

Подключившись к базе данных, требуется реализовать запросы к ней.

Опишу простой пример кода для этого.

Именование компонентов

Так как именование добавленных компонентов у каждого свое, приведу свой пример, с которым и будем работать:
  • TSQLQuery SQLQueryInstance
  • TSQLTRansaction SQLTransactionInstance

Код по шагам

 SQLQueryInstance.Close;
 
SQLQueryInstance.SQL.Clear;
 
SQLQueryInstance.SQL.Add('SELECT * FROM table_name');
 
SQLQueryInstance.ExecSQL;
 
SQLTransactionInstance.Commit;
 
SQLQueryInstance.Open;
  1. Сперва закрываем наш датасет
  2. Очищаем список SQL-запросов. На самом деле делать это не обязательно (все зависит от задачи). В данном примере, мне все равно, что за запросы были до этого - мне необходимо выполнить новый запрос и только. В целом, выполнятся все запросы из списка в свойстве SQL.
  3. Добавляем свой запрос. 
  4. Выполняем запрос без возвращения результата. В противном случае лучше использовать rawQuery.
  5. Коммитим транзакцию.
  6. Чтобы результат последней транзакции был виден grid-компоненту, открываем датасет.

Параметризация

Предположим, наш запрос предполагает работу с данными, полученными вне контекста БД.
К примеру, запрос на получение пользователя по его логину и паролю:
SELECT * FROM user WHERE login='user_login' AND password='user_password'
Предположим, логин и пароль были получены где-нибудь ранее и присвоены в качестве значения переменным login и password соотвественно. Теперь, запрос можно поменять следующим образом:
SQLQueryInstance.SQL.Add('SELECT * FROM user WHERE login=''' + login + ' AND password=''' + password);
Очевидно, что запрос приобрел несколько нечитаемый вид, вобрав в себя синтаксис SQL и Pascal, что несколько портит картину. Более того, приходится заботиться об экранировании кавычек.
Хочется сохранить целостность запросов, избегая дополнительной работы по отслеживанию кавычек и прочей рутинной, но синтаксически нужно работы.
Тут нам поможет параметризация sql-запросов.
В тех местах запроса, в которых мы предполагаем использовать "внешние" данные, мы ставим именованный плэйсхолдер, а затем отдельно указываем данные и тип данных: 
SQLQueryInstance.SQL.Add('SELECT * FROM user WHERE login=:login AND password=:password); 
SQLQueryInstance.Params.ParamByName('login').AsString := login;
SQLQueryInstance.Params.ParamByName('password').AsString := password;
В примере мы имеем два плэйсхолдера :login и :password, которые затем связываются с конечными данными, которые приводятся к тому или иному типу. В примере, оба параметра приведены к строковому типу через  свойство asString
Что примечательно, конечная вставка данных в запрос будет производиться на стороне базы данных, которая сама уже определит синтаксические особенности при работе с ними. Т.е., к примеру, при  передачи строковых данных, не нужно заботиться о кавычках - БД поставит их сама.
Так же, мы можем выполнить несколько однотипных запросов, меняя лишь данные, оставляя нетронутым сам запрос.
Параметризация в web-программировании - это один из методов борьбы с SQL-инъекциями.