42
General Information Home Who Are We? Contact Us What is Firebird? IPL License Events Blogs Paul Beach Philippe Makowski Dimitri Kuzmenko Other Languages www.ibphoenix.cz www.ibphoenix.fr Services Service & Support Training & Consulting Products Developer CD Deployment CD IBReplicator dbFile IBAnalyst IBFirstAid IBBackupSurgeon IBUndelete FBScanner Firebird Book Firebird Goodies Firebird Appliances Shop Online IBPhoenix Shop Development Firebird Development Vulcan Development General Documentation Function and Design Other Links Community Firebird Conference 2006 Firebird Conference 2005 Get Involved Member Websites Projects News News Archive Groups, Lists, and Forums IBPhoenix Development Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro... 1 de 42 06/04/2010 18:22

Delphi to InterBase in 15 M

  • Upload
    farope

  • View
    762

  • Download
    11

Embed Size (px)

Citation preview

Page 1: Delphi to InterBase in 15 M

General Information

Home

Who Are We?

Contact Us

What is Firebird?

IPL License

Events

Blogs

Paul Beach

Philippe Makowski

Dimitri Kuzmenko

Other Languages

www.ibphoenix.cz

www.ibphoenix.fr

Services

Service & Support

Training & Consulting

Products

Developer CD

Deployment CD

IBReplicator

dbFile

IBAnalyst

IBFirstAid

IBBackupSurgeon

IBUndelete

FBScanner

Firebird Book

Firebird Goodies

Firebird Appliances

Shop Online

IBPhoenix Shop

Development

Firebird Development

Vulcan Development

General Documentation

Function and Design

Other Links

Community

Firebird Conference 2006

Firebird Conference 2005

Get Involved

Member Websites

Projects

News

News Archive

Groups, Lists, and Forums

IBPhoenix Development

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

1 de 42 06/04/2010 18:22

Page 2: Delphi to InterBase in 15 M

Powered by Firebird

Users of Firebird

Publications

History

Web Hosting

Downloads

Main Downloads

InterBase®

Contributed

Research

Research Center

Articles

Examples

FAQs

Search

Search KnowledgeBase

Search Web Site

Search Mers List

Partners

Partners

This Site Uses:

Delphi to InterBase in 15 Minutes

Contents

Delphi to InterBase in 15 minutes

Chapter 1 - The 15 minute steps

Chapter 2 - 10 minutes to setting up InterBase

Chapter 3 - 5 minutes to setting up Delphi

Reducing the learning curve

Chapter 4 - Some practical issues

Chapter 5 - Delphi InterBase components

Chapter 6 - SQL

Chapter 7 - Stored procedures

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

2 de 42 06/04/2010 18:22

Page 3: Delphi to InterBase in 15 M

Status of the guide

Chapter 8 - Guide updates and limitation of liability

The text below references several demo files. These can be

downloaded by clicking on these three links:

DelphiToInterbasePAS.zip

DelphiToInterbaseSQL.zip

IBDemos.zip

Chapter 1 : The 15 minute steps

1.1 Setting up InterBase - 10 minutes

Step 1.1 - Create the database

Step 1.2 - Create the tables

Step 1.3 - Create the indexes

Step 1.4 - Populate the tables

Step 1.5 - Create stored procedures

1.2 Setting up Delphi - 5 minutes

Step 2.1 - Pop up a TIBDatabase component and fill in details

Step 2.2 - Pop up a TIBTransaction component and fill in details

Step 2.3 - Pop up a TIBTable component, a Datasource and a

DBGrid and DBNavigator

Chapter 2 : 10 Minutes to setting upInterBase

This Chapter is written on the basis that the InterBase SQL files

linked to this guide (Tables.SQL and Indexes.SQL) are open within

a simple text editor (such as Notepad or Delphi). If you read the

guide in conjunction with the SQL files, the points below should be

simple to follow.

2.1. Create the database

Background

First, you need to create the database. This is the file structure

within which InterBase will subsequently store both the table

structure, indexes etc. (called the Metadata), and the data itself

(called the Data).

Do it!

To create the database:

Open IBConsole (Problems? Go to Using IBConsole)1.

Click "Database, Create Database"2.

Enter the Database path name and database name3.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

3 de 42 06/04/2010 18:22

Page 4: Delphi to InterBase in 15 M

(Networks? See Database locations)

Enter user name and password (Special considerations? Go to

creating a database in IBConsole)

4.

Click the "Create" button5.

2.2 Create the tables

Background

Next, create the table structures. This can be achieved in several

ways. The easiest way is to take a simple text file, fill in the table

structure, and "import" the structure to InterBase using IBConsole,

as explained below. There is a separate section covering "Importing

database changes using a SQL file" which will be of interest when

you need to carry out the Importing process for the second time.

A simple text file has been provided with this guide (Tables.SQL)

with illustrative file layouts. Change the layout(s) to the layout(s)

you require, and import the structure into InterBase. You can

change it easily later. Those who don't feel comfortable with what

they are doing might want to see Creating tables - Tips, prior to

"doing it".

Do it!

To create the tables:

Open "Tables.SQL" in any text editor (eg. Notepad, Delphi)1.

Change the file location within the "Connect" statement to

the location to which you saved the Database

2.

Change the "user" and "password" to the username and

password used to create the database

3.

Change the Table layout to the layout you want. (Want help

with Datatypes? See InterBase Datatypes)

4.

Save the file (Latest changes not used by InterBase? See

Creating tables - Tips )

5.

In the program IBConsole, click "Query, Load script"6.

Find the SQL file you saved, and click "Open".7.

Comment out the "Connect ... " statement (How? See

Comments paragraph in Chapter on SQL)

8.

Click "Query, Execute"9.

If you want the confirmation and/or the error messages to

appear in the IBConsole window, click the "No" button. If you

prefer them to be saved to disc in a simple text file, click the

"Yes" button and give the program a file name and location to

which the results will be written.

10.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

4 de 42 06/04/2010 18:22

Page 5: Delphi to InterBase in 15 M

If successful - you will be told (well done!). (Failure? See

Handling SQL script errors)

11.

2.3 Create the indexes

Background

Indexes allow InterBase to locate data (dramatically) more quickly.

An index has two key components to it - the field(s) that you will

want to search on and whether the field(s) are unique (e.g. a

Reference number will probably need to be unique, but you may

well need to accommodate several people sharing a birth date or a

last name).

One particular type of index that is usually needed is an index on

the Field(s) which uniquely identify a record within a table (e.g. the

unique reference number given to each record, or a Social Security

ID, or a post code and House number/name combination within an

Address table). This is called the Primary key. Those who don't feel

comfortable with what they are doing might want to see Creating

indexes - Tips, prior to "doing it".

Do it!

Creating the Primary Key

Open your "table.SQL" file.1.

Add a line at the bottom of the definition, immediately before

the final ")", and add the phrase (with the comma in front)

, PRIMARY KEY (field)

where field is the name of the field(s) you want as the

primary key, eg:

, PRIMARY KEY (REF) or another example: , PRIMARY KEY

(LASTNAME, FIRSTNAME, POSTCODE)

2.

If you have already created your table, see Creating indexes

- Tips

3.

Creating other Indexes

Open the "Indexes.SQL" file1.

Add a new index with the syntax (don't forget the semi-colon

at the end): CREATE INDEX NAME ON ANIMALS(NAME);

where "Animals" is the name of the table, and "Name" is the

field on which to index (sort)

2.

2.4 Populate the tables

Background

When the database has been created, and the structure set up, you

may want to fill up the database with test data. This can be

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

5 de 42 06/04/2010 18:22

Page 6: Delphi to InterBase in 15 M

achieved through the "old-fashioned" technique of manually

entering data into the database (especially if you have already set

up the Delphi side which allows data entry).

A more robust technique is to create a series of SQL commands

that insert data to the table within a simple text file, and import

the SQL file to InterBase.

The advantages of this approach include the ability (a) to copy,

paste and update lines to achieve a methodical selection of all types

of data more easily, (b) to re-enter the data whenever you choose

to clear all the data from the database and start again and (c) to

reuse relevant test data within new database applications in future.

Do it!

To populate the database using this method:

Open "TestData.SQL" in any text editor (eg. Notepad, Delphi)1.

Change the file location within the "Connect" statement to

the location to which you saved the Database

2.

Change the "user" and "password" to the username and

password used to create the database

3.

Amend the test data. (Why this format? See InterBase SQL

reference guide - "Insert" commands)

4.

Save the file (Latest changes not used by InterBase? See

Handling SQL script errors )

5.

In the IBConsole program, click "Query, Load script".6.

Find the SQL file you saved, and click "Open".7.

Comment out the "Connect.." statement (How? See

Comments paragraph in Chapter on SQL ). Click "Query,

Execute"

8.

If you want the confirmation and/or the error messages to

appear in IBConsole, click the "No" button. If you prefer them

to be saved to disc in a simple text file, click the "Yes" button

and give the program a file name and location to which the

results will be written.

9.

If successful - you will be told (well done!). (Failure? See

Handling SQL script errors)

10.

2.5 Create stored procedures

Why and when?

Stored procedures are arguably some of the most powerful features

of InterBase.

Almost (but not quite) everything that can be achieved through

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

6 de 42 06/04/2010 18:22

Page 7: Delphi to InterBase in 15 M

Stored Procedures can also be achieved by sending SQL commands

from Delphi to InterBase. But the programming time can increase

well more than tenfold, and the running time can increase by vast

factors in certain circumstances. To start using InterBase, stored

procedures are not necessary. To program Database applications

more quickly and to run faster, it is well worth learning how to use

Stored Procedures - a learning curve that should be shallow for

most programmers with the help of the Stored Procedures section

in this guide. Some background to Stored Procedures is set out

below:

Background

Stored procedures fall into two main categories:

procedures that update the Database's Metadata (What's

that? See Create the database).

1.

procedures that handle the Database's data, such selecting

specified items (eg. people older than 12) or modifying data

(such as inserting a new address, editing an existing address,

updating a wage rate by a calculated percentage or deleting a

group of employees from a table where the record matches a

record in another archive table)

2.

The stored procedure is similar in concept to a Delphi procedure or

function. It is programmed directly into InterBase to:

accept input parameters (if there are any), provide formatted

output parameters giving single item output (such as the

total of relevant sales invoices),

1.

provide formatted output parameters (if there are any) giving

a result set (such as every invoice detail that corresponds

with an invoice reference), or

2.

simply modify the database information using conventional

programming techniques (such as updating records if the

department value is greater than one value but less than

another)

3.

The stored procedure can be "called" either from within a Delphi

program (How? See the Delphi components section), from within

another InterBase Stored Procedure (using the InterBase SQL

command Execute Procedure ) or from any other program capable

of "calling" the stored procedure (such as the IBConsole program

that comes with InterBase).

The syntax used to "call" the stored procedures depends on what

the stored procedure does. An example of the syntax would be

SELECT * FROM SP_NEW_RECRUITS('4/1/1999','12/1/1999') to

select all new recruits who joined a company within two dates, and

EXECUTE PROCEDURE SP_ARCHIVE_RECORDS('Sales and

Marketing') to archive records from the Sales and Marketing table.

The use of Stored Procedures is so powerful, there is a section even

in this "Introductory" guide to InterBase, with some examples of

Stored Procedures we have used within our own programs to

illustrate the power and syntax of the facility - see the Chapter on

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

7 de 42 06/04/2010 18:22

Page 8: Delphi to InterBase in 15 M

Stored Procedures. The full technical specification of using Stored

Procedures can be found in the InterBase manuals, in several

places depending on what you are looking to achieve).

Chapter 3 : 5 minutes to setting up Delphi

This Chapter is written on the basis that the Demo Delphi project

"DelphiDemo.dpr" linked to this guide is running within Delphi. If

you read the guide in conjunction with the program, the points

below should be simple to follow.

3.1 Database component (TIBDatabase on

InterBase tab)

Drop a TIBDatabase component onto a Form (or DataModule if you

use them). The configuration is in two places:

Object inspector

Connected - leave as false. Set to true when ready to see if

the component is set properly.

1.

Database name - Fill in the file location and name (File can't

be found? See Database locations)

2.

Default transaction - See TIBTransaction component below3.

Login prompt - If you want users to login, leave as false. If

not, set to true AND see step c.

4.

Params - set if step c. is not enough5.

Double click on the component for the Property editor

Connection - leave as "local" if InterBase is running on your

machine. Otherwise, set to "remote" and see InterBase

Network issues

1.

User Name - Enter the UserName used to create the

Database (but note points relating to Login prompt). Leave

blank if you do want the User to type in their own User name.

2.

Password - Enter the Password used to create the Database

(but note points relating to Login prompt)

3.

Login Prompt - Set to Ticked if you want users to enter their

username and password. Set to Blank if you want InterBase

to use the UserName and Password you have entered in the

TIBDatabase Component (see above). Note - InterBase gives

you the capability to allocate different users with different

rights. If you want to make use of this facility, you will need

to leave the Login prompt ticked.

4.

There is a trap for the unwary when opening and closing a

database using the component. To avoid the trap, see

Opening and Closing a database using Delphi - Tips

5.

3.2 Transaction component (TIBTransaction

on InterBase tab)

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

8 de 42 06/04/2010 18:22

Page 9: Delphi to InterBase in 15 M

Background

InterBase allows you to collect a group of modifications and

commands together and process either all of them or none of them.

The commands are, of course, processed sequentially (such as

Check stock line exists, then if it does, update the stock table, then

issue a sales invoice, then update the sales table).

The problem that InterBase solves is where there is a break after

some transactions have been processed, but before others within

the collection have not. An example is where stock is updated but,

for some reason, the sales invoice should not be raised. Without

solution, the stock level would no longer "match" the sales levels.

With the solution, InterBase collects all commands (also called

transactions) together, processed the batch and if anywhere along

the line there is a failure before all the transactions are completed,

all transactions that have already been processed are rolled back).

InterBase solves the problem by allowing the Delphi programmer to

"mark" within the Delphi program where a collection of commands

starts (with the Delphi command TIBTransaction.StartTransaction)

and where it ends (with the Delphi command

TIBTransaction.Commit or TIBTransaction.Rollback. When each

transaction is "processed", it is simply held in a temporary location

with the command being carried out only on a temporary basis,

pending the Commit command. When the programmer issues the

command TIBTransaction.Commit in the Delphi program, all

transactions within the group are finally processed. When the

programmer issues the command TIBTransaction.Rollback in the

Delphi program, the commands are removed from the temporary

location and the data restored to the state prior to the first

command where the StartTransaction command was issued.

There is one conceptually strange aspect to the Transaction

component. InterBase will not operate other than in the context of

a Transaction. However, once the Transaction component has been

hooked up (see below), there is no requirement that you activate

the Start and End of the Transaction in your program. If the

Transaction is in place, you are able simply to issue a database

command (say, to update a record in a table), and the Transaction

assumes you mean for it to start just before the command is

processed, and for it to end just after the command has been

processed, unless you override the default behavior with the

StartTransaction and Commit/Rollback instructions. The

Transaction will be committed for you when the Database is closed

(or when the program is closed if that comes first).

Do it!

Drop a TIBTransaction component onto the Form (or DataModule if

you use them). To configure the component:

All defaults can be accepted1.

In the TIBDatabase component, set the Default Transaction to

the name of the TIBTransaction just created.

2.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

9 de 42 06/04/2010 18:22

Page 10: Delphi to InterBase in 15 M

3.3 Displaying the InterBase data in the Delphi

program

Background

Once the TIBDatabase and TIBTransaction have been set up,

everything is programmed as any other database application.

Do it!

To display the InterBase Database:

Pop a TIBTable component onto the form (from the InterBase

tab)

1.

Set the Database property to the TIBDatabase component's

name

2.

Set the Table property to the Table you want to display3.

Pop a TDataSource component onto the form (from the Data

Access tab)

4.

Set the Dataset property to the TIBTable component's name5.

Pop a data aware control, such as a TDBGrid (from the Data

Access tab)

6.

Set the Datasource property to the TDatasource component's

name

7.

Pop a TDBNavigator on the form (from the Data Access tab)8.

Set the Datasource property to the TDatasource component's

name

9.

Set the TIBTable's "Active" property to True10.

Save and run the program11.

Chapter 4 - Practical issues

4.1 Creating tables - Tips

4.2 Creating indexes - Tips

4.3 Opening and closing a Database from Delphi - Tips

4.4 Database locations

4.5 Network issues

4.6 IB Console - Running SQL files

4.7 Creating a SQL script file

4.8 Handling SQL script errors

4.9 InterBase Datatypes

4.1 Creating tables - Tips

This section expands on Creating tables from section 2.2. It is

designed for those who don't feel comfortable creating tables

without some further guidance. For a detailed specification on

creating tables, see the InterBase guide "Data Definition Guide".

Every comma and semi-colon is significant. Watch for

inadvertent deletions. (More detail? See Creating a SQL

script)

1.

If you are unsure whether you want a Primary Key, see (2.3)

Create the indexes.

2.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

10 de 42 06/04/2010 18:22

Page 11: Delphi to InterBase in 15 M

Don't use referential integrity facilities at this stage3.

Keep the file structure simple. It is easy to make it more

complex later.

4.

Don't fill in large amounts of test or real data to a

column/field that may subsequently change, since it is a

fiddly process to change the definition of a column/field (eg. a

REF field from an INTEGER to a VARCHAR(10), or an

AMOUNT field without a default value to an AMOUNT field

with a default value ) which already has data in it.

5.

When you have amended an "SQL" file, save it before

importing it. Otherwise, InterBase will import the version

before you made any amendments - or, more accurately, the

version that was last saved.

6.

4.2 Creating indexes - Tips

This section expands on Creating indexes from section 2.3. It is

designed for those who don't feel comfortable creating indexes

without some further guidance. For a detailed specification on

creating indexes, see the InterBase guide "Data Definition Guide".

If you want to create a Primary key, and you have already

created the table, the format of the SQL command to achieve

the Primary key is:

ALTER TABLE ITEMS ADD PRIMARY KEY (REF);

although you can not create a second primary key if one

already exists

1.

For details of the Create Index rules, see "Create Index" in

the InterBase SQL reference manual.

2.

4.3 Opening and closing a Database from

Delphi - Tips

One tip - in the BDE, the Database is closed for you when you exit

the program. This is not so with the InterBase Express components.

The solution is to have a IBDatabase1.close statement in the

Form.OnClose event (or similar). If you forget to close the

Database explicitly, it stays "open". If you try to open a database

that is already open, using the TIBDatabase component, you get an

error message. The solution is always to check with the database is

open before opening it (eg. of Delphi : if not

(IBTransaction1.connected) then IBTransaction1.open; ) and closed

before closing it (eg. of Delphi : if (IBTransaction1.connected) then

IBTransaction1.close; - Note that when you close a database, the

Transaction and any other component "connected" to that Database

is also disconnected for you, whether you intended it or not.)

4.4 Database locations

The InterBase components do not work with the BDE, so no Aliases.

Instead, you need to use the absolute location when filling in the

location of the database (and its file name).

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

11 de 42 06/04/2010 18:22

Page 12: Delphi to InterBase in 15 M

In Windows, file locations follow the familiar pattern

"c:generalInterBasefilename.txt". For a networked drive, (mapped,

say to f: which is on the machine name "Machine2"), the pattern

for the location is "f:generalintertbasefilename.txt"

InterBase is well geared up for dealing with both internal and

external networks. It has to be a little more sophisticated. In some

circumstances, this notation works fine. In others (particularly

where you are involved with internet Web applications and/or the

TCP/IP protocol within your internal network), you have to precede

the file location name with the machine name, eg.

"Machine2:c:generalInterBasefilename.txt". Note the absence of

the "" character between the machine name and the machine's

local file location.

When using TCP/IP, you will need to "tell" InterBase where the

machine (eg. Machine2) can be found. This is done very easily by

editing the file called "hosts" (note not hosts.sam, which is

something quite different). This file can be in more than one place,

and is easily found by a Windows search of the Windows or WinNT

directories (including sub-directories) for the file "hosts" (in our

configuration, Hosts is found in the WinNTSystem32driversetc

directory). When found, open the file with a simple text editor

(such as Notepad or Delphi) and add at the end of the file the line

which "identifies" the IP address with its machine name.

An example of the entries might be (note that the # sign means a

comment follows):

#IP

address

#Machine

name#Comments

127.0.0.1 localhost

192.1.1.1 Machine1#This is a local machine with

address 192.1.1.1

192.1.1.2 Machine2#Local machine, referred to

as Machine2 by programs

99.876.78.9 MyISPMachine#External machine with

address 99.888.77.66

Another possible file you may need to edit is the Services file. You

can find it the same way as you found the hosts file. InterBase

needs to have the line below added in. It should have been added

in automatically during installation. But on occasions, you may

have to add it "manually. If so:

Open the Services file1.

Add the line below

gds_db 3050/tcp

2.

4.5 InterBase - Network issues

InterBase can work with three network protocols, TCP/IP,

NamedPipe and SPX. InterBase must be configured to use the

protocols used by your network.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

12 de 42 06/04/2010 18:22

Page 13: Delphi to InterBase in 15 M

If you have the choice, use TCP/IP, since there are situations where

the others will not run. For a detailed explanation of the

performance issues where you have the choice of protocols to use,

check out the InterBase manuals.

If you are using TCP/IP, be sure to check out the section on

Database locations.

4.6 Using the IBConsole

IBConsole is a program written to allow easy access to InterBase. It

enables you to create a Database, to set up and amend the

Metadata (what's that? See Create the Database), and to insert,

update, delete and query data in the database.

This guide explains just a few of the issues relating to using

IBConsole, to encourage its use for "no fuss" access to the

database.

Open the program (for Windows users .. "Start, Programs,

InterBase 6, IBConsole"), then

To create a new database, click "Database, Create Database",

and fill in the blanks. For assistance, the database name must

include the path to the directory in which you want to store

the database. The Username and Password are important in

the respect that it is the default name and password

combination that give you full access to the database in

future. Do not use generic names/passwords (such as

"SYSDBA" and "masterkey") if you want to control people

accessing the data who you may have concern about access.

Conversely, try to avoid setting up a database whose name

and password you can not remember - you will not be able to

connect to it from the time you have forgotten. If you have to

use a "Remote server", and you have to make a selection

about which network protocol to use, try the TCP/IP protocol

if your network has access to TCP/IP and if don't have a clue

about the others.

1.

If you have already created a database, click "Database,

Connect", and fill in the blanks. Once you have connected to

a Database, you then have full access (subject to the rights to

which you may have been constrained by someone else with

control over the Database you are reviewing).

2.

Much of the time, you will want to run SQL commands. For

this you use the ISQL window, which you get access to by

clicking "Tools, Interactive SQL"

3.

The top window allows you to enter SQL commands

(Examples? See the Chapter on SQL). This is particularly

useful for checking whether a SQL statement does what you

expect, before entering it into a Stored Procedure. To

"execute" the command, type it is and click the Lightening

hot key (or click "Query, Execute). To rerun (or pull up to

amend) a previous query, click the back arrow with the

symbols "<--?", make any changes you want, and execute

the command again.

4.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

13 de 42 06/04/2010 18:22

Page 14: Delphi to InterBase in 15 M

The bottom window contains the results of the query. If you

want to print the output, you can click "Query, Save output",

give a file name and open the text file in any simple text

editor (such as Notepad or Delphi).

5.

To disconnect from a database, click "Database, Disconnect".6.

When you have "executed" an action in the top window, you

generally have the option to Commit or Rollback (via

"Transaction, Commit" or "Transaction, Rollback"). Rolling

back reverses any change to the database since the start of,

if later, the previous commit or rollback. Committing does two

things. Firstly, it makes permanent any changes you have

made to the database (metadata and/or data). Secondly, it

"refreshes" your dataset. If you are working on a database

file, and the data is changed outside of the IBConsole (

EITHER by someone else OR you where you change the data

through, say, a test Delphi program or through another

instance of IBConsole connected to the same database), the

changes are not reflected in your session of IBConsole which

is working on a cached version of the data. When you Commit

or Rollback, the cached version is "thrown away" and you will

access the current version of the data from the main

database itself. The Commit command will clear the output

window at the bottom, so you will have to re-run your SQL

query, for which you can use the "<--?" hot key.

7.

The final - and crucial - guide in this section explains how to

"import" SQL to the database. You always have the option to

type the SQL commands directly in the top window. But there

are several commands that are better to enter in groups

(such as the setting up of a table, whose structure is far

easier to formulate as a group, than entering each field one

by one). In order to import the SQL, set up a simple text file

in any text editor (such as Notepad or Delphi), and save it

with the extension "SQL" (not mandatory, but it saves one

step further along the line). See the section on Creating a

SQL script file for what to include in the file.

When you are ready, save the SQL file. Within the ISQL

window, click "Query, Load script". Find the file, and click

"Open". You then need to comment out the "Connect.." or

"Create database.." statements. Comment out means enclose

the statements within the comment symbols (eg. of sql : /*

Connect database 'IBDemos.gdb' */ ). The statement has to

be in the script to allow you to run the SQL script from

outside IBConsole, but IBConsole will not allow you to run a

script without having first connected to an existing database.

The solution is simple - connect to the database first. (How?

See parapraph on connecting). Then, to execute the script,

click "Query, Execute".

The results of the Execution will either be "Your request was

successful" (in which case, well done), or it will give you an

error message. Every error we have ever encountered at this

stage has been Syntax errors. The error messages are close

to the most cryptic and unhelpful you may ever encounter.

For this reason, we would recommend you take very careful

note of the syntax rules in Creating a SQL script file, and try

8.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

14 de 42 06/04/2010 18:22

Page 15: Delphi to InterBase in 15 M

to avoid making mistakes in the first place - which is

surprisingly possible.

4.7 Creating a SQL script

A SQL script is a simple text file that contains a series of SQL

commands that are run together as a series. There are many times

this is preferable to entering SQL directly to a database line by line

through IBConsole (What? see Using IBConsole). Using a SQL script

file is very easy, but as with all program code, the Syntax has to be

exact, and the rules appear inconsistent and run contrary to the

instinct of a Delphi programmer.

The easiest way to get the script (and the Syntax) right is to crib

from an existing file with the correct syntax. The zip file contains

several files with the extension ".SQL". You should open one of

them when looking through this part of the guide to make it easy

to understand what is going on.

To put a comment within the SQL script file, use the symbols

/* to start the comment, and */ to end it. Carriage returns

within a comment do not "cease" the commenting out. (This

is more useful that you would imagine - see the last

paragraph in this section for one circumstance where the

commenting symbols are invaluable)

1.

The "Connect" statement is essential. This both connects to

the Database you want to update, and enters the Username

and Password (eg. of sql : CONNECT

"machine1:c:generaldataIBDemos.gdb" USER "SYSDBA"

PASSWORD "masterkey"; - Note that the machine name is

required without "" if connecting to a database on another

machine, and note the position of the semi-colon at the very

end)

2.

There are two kinds of SQL you will enter. One kind is an

entirely self contained statement (such as SET GENERATOR

ORDER_GEN TO 138; - there is no break anywhere in the

statement which is relevant to InterBase ), and the other is a

series of statement that can not be interpreted without

identifying there is a break within the statement (such as

CREATE TABLE ORDERSDETAIL (REF INTEGER NOT NULL,

ORDERREF INTEGER NOT NULL, STOCKREF INTEGER NOT

NULL); - without the comma, InterBase would not have know

whether ORDERREF was the start of a new field or an error in

typing). The problem this paragraph deals with involves

identifying a break which represents the end of the

statement, distinguishing it from a break within the

statement. The problem arises only because the standard

Delphi symbol used for a break is the semi-colon (';'). This

break symbol is used within a stored procedure to identify

that the end of a SQL statement has arrived and the next

SQL statement is coming. And it is also used within a SQL

script to identify that the next SQL script statement is

coming.

The solution provided by InterBase is to allow you to define

your own "break" symbol for the SQL script file. When you

set this symbol (we use '^', others use '!!', and you can use

3.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

15 de 42 06/04/2010 18:22

Page 16: Delphi to InterBase in 15 M

whatever you feel comfortable with), you continue to use the

';' symbol to identify the break of a sql statement within a

stored procedure, but to identify the break of the SQL script

statement (such as to denote the end of the Stored Procedure

itself), you then use your self-defined symbol.

To set InterBase to start to recognise the break symbol, use

the instruction : SET TERM ^ ; - Note the semi-colon is still

required to denote the end of this SQL script statement. To

switch this symbol off, use the instruction SET TERM ; ^ -

Note the self-defined break symbol is still required to

terminate this statement, but all subsequent statements will

break with the conventional ';' symbol. Within the SET TERM

pair of instructions, any SQL script statement termination

uses the defined symbol (eg. of sql : SET GENERATOR

ORDER_GEN TO 138^ ). BUT, where you are creating a

stored procedure with distinct SQL statements within the

Procedure, each statement must continue to use the

conventional ';' symbol, or the Stored Procedure will not

operate properly when it is at a later date.

This solution, which is not really so cumbersome once you

have the Syntax right, is confused by the way that a BEGIN ..

END pair is terminated in an InterBase stored procedure.

Where the BEGIN .. END is within the definition of a Stored

Procedure, you do not terminate the END statement, other

than at the very end of the Stored Procedure where you use

the self-defined SQL script termination symbol to denote the

end of the Stored Procedure. But within the Stored

Procedure's definition, you may use a begin .. end set within

an 'IF' type clause, in which case the End IS terminated with

the ';' symbol. For more details, see the Chapter on Stored

Procedures.

The SQL script file is usually "closed" with the "COMMIT"

statement, to commit to the database changes that occurred.

4.

If you ran a script that failed, you will find that the part that

"succeeded" prior to the failure will have been committed to

the database. Therefore, the next time you run the script,

you may find a new error message saying that you are trying

to create something that already exists. The solution is to

comment out any statements that have been "passed" on

importing.

5.

4.8 Handling SQL script errors

You import a series of SQL statements into InterBase, typically to

set up Metadata and to insert test data to the Database (How? See

Creating a SQL script). If and when you import a script with Syntax

errors, IBConsole provides you with inadequate error messages.

Throughout this guide are tips to help you avoid error. This section

provides you with the links for information on avoiding and

handling errors on importing.

Create, import and execute a script - see Creating a SQL

script

1.

Error messages for sections that have not previously been2.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

16 de 42 06/04/2010 18:22

Page 17: Delphi to InterBase in 15 M

reported - see Creating a SQL script, final paragraph

Unable to connect to the Database - see Creating a SQL

script, CONNECT paragraph

3.

Errors related to end of statements - see Creating a SQL

script, TERMINATIONS paragraph

4.

Corrected errors failing to be picked up by InterBase - If you

amend a text file to correct an error, it is not saved to disk

until you save it. Therefore, remember to save the file

WHENEVER you make any changes. If you have corrected an

error, check the output to confirm which version of the file

InterBase has just tried to import. If is the pre-saved version,

simply save the corrections in your text editor and re-run the

SQL script.

5.

One final point - InterBase identifies where there is an error

by reference to the line count. For this purpose, InterBase

ignores lines without any data. So the 32nd line, is not

necessarily the 32nd line in your file. One solution is to put in

a know error towards the top, run the script and note the line

number of the known error. Keep moving the error down and

re-running the script until you are able to identify the

problem script.

6.

4.9 InterBase Datatypes

There are only a few datatypes within InterBase, and they are

largely instinctive to a Delphi programmer. The InterBase manuals

give the technical specification of different datatype (eg. integer).

There are a couple of datatypes listed below for which you may find

that you may a small amount of guidance saves you a large amount

of time.

Strings - The InterBase equivalent of Strings is VARCHAR(25)

or CHAR(22) . The number in brackets is the number of

characters you want the string to have. A CHAR definition

reserves the number of characters you have specified in the

database, irrespective of the number of characters in the

string (eg. of sql : Name CHAR(50); will allow you to enter

any name up to 50 characters, and InterBase will store 50

characters on disk, even if the name has less characters

(such as 'Smith'). A VARCHAR definition puts an upper limit

on the number of characters you are entitled to save, but will

only use the number of characters in the saved name (5 in

the above example). If you try to put a string with more

characters than the defined field length, the string gets

truncated and you lose the truncated characters.

1.

In earlier versions of InterBase, Floats had a different

concept of decimal point numbers to Delphi. A number was

stored in InterBase with all its decimals, up to the maximum

InterBase can store. If you stored a number, say 4.22, this

was stored within InterBase as 4.2200000012651 (or

something like that). If you stored the result of 4/3, it was

store 1.333333333315561 (or something like that). The

Datatypes available to you affected ONLY the formatting for

display purposes. They ido not affect the storage of the data.

2.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

17 de 42 06/04/2010 18:22

Page 18: Delphi to InterBase in 15 M

The two main types of decimal definitions were

NUMERIC(15,2) and DECIMAL(22,5), where the first number

was the length of the number and the second number was

the number of decimal points. The difference between the two

above numbers are subtle and explained in the InterBase

manual - Data definition.

To avoid rounding errors when dealing with currencies, you

had to round any number you wanted to store to 2 decimal

places prior to saving. This prevented the result of storing

'4/3', and adding it to another stored '4/3' from giving you a

result that does not match the displayed sum of '1.33' +

'1.33'.

Under the new versions, the method of storage and

implementation of the number system has changed. For this

reasons, users migrating from earlier versions of InterBase to

version 6 should pay particular attention to the InterBase

Manual - Getting started, Section "Migration issues"

Dates - Separate datatypes exist for Date, Time and the

datatype TimeStamp, which is the equivalent of a TDateTime.

If you want InterBase to use a date field, say in an output

report, you need to use the "Cast" methods within InterBase.

(How? See SQL:Sundry)

3.

Chapter 5 - Delphi InterBase components

The Delphi InterBase components are described very well in the

InterBase manual - "Developers Guide". This section is designed to

help understand some of the concepts that are not necessarily

apparent to a programmer who is new to the components.

Component Function

TIBDatabase The Database component

TIBTransaction The Transaction component

TIBTable The Table component

TIBQuery The Query component

TIBSQLThe "unidirectional" Query

component

Updating read-only

dataset

ExplanationBackground to updating Read-Only

datasets

TIBUpdateSQLThe simple Read-Only updating

component

TIBDataSetThe self-contained Read-Only

updating component

Stored procedures

TIBStoredProc The Stored Procedure procedure

5.1 TIBDatabase/TIBTransaction/TIBTable

These components are explained in Chapter 3, Setting Up Delphi.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

18 de 42 06/04/2010 18:22

Page 19: Delphi to InterBase in 15 M

5.2 TIBQuery - The Query component

This component is designed to be the main Query component that

is used. The "Query" component allows you to send through any

SQL command to InterBase. It's power can be seen when dealing

with a result set of multiple records. This component is one that

brings the full power of InterBase's reporting facilities to Delphi, by

allowing you to use SQL commands from Delphi. For a guide to the

power of SQL commands, see the Chapter on SQL

Note that the TIBQuery result set is read-only. For those who want

to display a result set within a data-aware component (say a

TDBGrid or TDBEdit) for users to have immediate ability to update,

you will need to implement the TIBDataset component to give your

users this facility. - BUT REMEMBER that you have to set the

TIBQuery's "CachedUpdates" property to "true" before it will work.

There are growing number of programmers, however, who perfer to

"collect" data from a database, fill in each record into an Object

they create, and get the Object to feed unmodified data to the user

and modified data to the Database- this gives the Programmer

additional control and faster upgrades and maintenance later in the

programming cycle in exchange for more complex programming in

the earlier stages of the programming cycle. The TIBQuery is

perfect for this type of use.

To send off a SQL query to InterBase:

Fill in the Database name property1.

Fill in in the SQL property (eg. Select * from sales where

sales_value > 50000 )

2.

Run the SQL query from the Delphi program, using the

command TIBQuery.ExecSQL).

3.

The result set can be used in just about any way, such as

hooking it up to a Data Aware control (like TDBGrid),1.

scrolling backwards and forwards (using, say, a

TDBNavigator, or using the IBQuery1.Next and

IBQuery1.Previous command to move backwards and

forwards programmatically)

2.

using and filling in parameters eg:

In the SQL property, use the statement

Select Firstname, TelephoneNumber from Customers where

Lastname=:LastnameParam

In the program at runtime, use the statement

IBQuery1.Params.ParamByName('LastnameParam').AsString

:='Smith';

3.

querying data from more than one table at a time, such as

with the statement

Select Person.Firstname, Person.Lastname, Address.County

from Person, Address where Person.AddressRef=Address.Ref.

4.

It's downside is that it takes up more overhead. We have yet to find

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

19 de 42 06/04/2010 18:22

Page 20: Delphi to InterBase in 15 M

a situation where it has significantly affected our program, but if

this is significant to your application/hardware configuration, check

out the TIBSQL component for an alternative in restricted

circumstances.

5.3 TIBSQL - The "unidirectional" query

component

This component is designed to be quick and basic, or to use

"minimal overhead" in Delphi speak.

It is used by filling in any SQL command in the SQL property,

and executing it using the command TIBQuery.ExecQuery .

It's upside is that is really is a very quick and simple way to

pass through any SQL command to InterBase. So for queries

that, count the number of records in a selected group where

the result is a single number, the SQL command is very

effective. An example might be

Select count(ref) from employees where

DepartmentName='IT'

It's downside is its handling of results. If the query returns

many records, the IBQuery can only handle moving forward

through the result set. This means that you can comfortably

transfer all records to, say, a separate object for each record.

But you can not go forward two records, then go back, say,

one record. This makes scrolling impractical for most uses.

Further, the IBSQL component does not hook up to data

aware components. So if you want to display the result set

through Data Aware components, the TIBQuery is not for

you.

Background to updating Read-Only datasets

The two components, TIBUpdateSQL and TDataSet are examples of

the few "indirect" components that are used in InterBase Experss.

(Eh? Read on..).

There are times where you will want to pull together a query

which is read-only (such as a TIBQuery or TIBSQL) , into a

data-aware component that your Program user can update

"directly" through a Data-Aware control.

The Read-only components are read-only because too often

there may be an ambiguity to InterBase about how to handle

the update. An example is where a query extracts data from

more than one table, which is put into a single TDBGrid for

the user to update, such as matching an employee's name

from the Employee table, with his/her address from the

Address table, where the first and last name are

concatenated into a single "name" field in the TDBGrid. In the

"simple" situation of a Table fed directly into a TDBGrid, the

user can change details and post them, and the changes are

updated immediately. In the possible "ambiguity" situation,

InterBase will not take responsibility for ensuring that the

correct fields have been updated.

The TIBUpdate component is Delphi's solution to allow you to

specify precisely what data modification should take place in

the database, whenever the TDBGrid (or other data aware

component), which may contain data from more than one

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

20 de 42 06/04/2010 18:22

Page 21: Delphi to InterBase in 15 M

table (such as in a SQL join statement), is "posted".

The value of understanding that the component is indirect is

to help you use this very powerful tool. The "indirect" part

comes because a user instructs the program to "post" a

queried datatset, and the Delphi program redirects the Post

from the initial "read-only" component, to another component

that is never directly called. Note that you need a separated

"indirect" component for each table you want to update. If

the "post" needs to modify data from a single table, then you

should use the TIBUpdateSQL component. If the "post" needs

to modify data in more than one table, you need to use the

TIBDataSet components - a separate one for each table to be

updated.

5.4 TIBUpdateSQL - The simple Read-Only

updating component

Be sure to read the Background section before trying to understand

this section. The TIBUpdateSQL only works where one table alone

needs to be updated. Where you want to update more than one

table, use the TIBDataSet components.

The TIBUpdateSQL requires you to specify four different SQL

commands, one which effects each of Edit, Insert, Delete or

Refresh. (What SQL works? See the Chapter on SQL.)

Remember, this is the Indirect component that is called

automatically by another component that is linked to this

one, and is not called explicitly in your program.

1.

Once you have set up the TIBUpdateSQL component, go back

to the "originating" component, such as a TIBQuery

component. In the originating component, select the relevant

TIBUpdateSQL in the UpdateObject property. Also set the

"CachedUpdates" property to True.

One word of caution : Caching is Delphi's equivalent to the

InterBase Transactions handling (What's that? See

TIBTransaction in Setting up Delphi). Setting the Caching

property to "true" means that updates will be stored

temporarily, and will not be made permanent until you use

the Delphi command QueryName.ApplyUpdates, or

QueryName.CancelUpdates. The caching is entirely

independent of InterBase's Transaction handling.

Conceptually, Delphi does not pass through changes to

InterBase until the ApplyUpdates is called, at which point

InterBase treats it as any other data entry, which is not fed

through permanently to the actual database until the

InterBase command Commit or Rollback is called. Of course,

if you are not using Transaction handling in InterBase, then

the changes fed through to InterBase are fed through to the

actual database immediately the ApplyUpdates command is

called in Delphi, in the same way as any other data update.

See the InterBase manual - Developers Guide for more

details on handling cached data.

2.

The selection of which of the four SQL commands to operate

is made by the TDBNavigator action. This is, of course, what

happens when using a "conventional" Navigator and

Data-Aware component, but you are normally shielded from

3.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

21 de 42 06/04/2010 18:22

Page 22: Delphi to InterBase in 15 M

this process where there is no ambiguity. The

"onUpdateRecord" event handler will be passed a parameter

"UpdateKind" which allows you to know which request you

are dealing with.

You will probably be glad of the "OnUpdateRecord" event

handler in the "originating" component, such as a TIBQuery.

If, for example, you want to deal with NULL fields that

InterBase is set up to reject, to fill in parameter values or to

carry out any other validation, here is a good place to write

your code.

4.

If you have not specified the "UpdateObject" property in the

originating component, you can apply the appropriate SQL

command, in the OnUpdateRecord, use the "apply" command

(eg. of Delphi: IBUpdateSQL1.Apply(UpdateKind); ). This

allows you to use more than one IBUpdateSQL's if you need

to. If you do use this facility with a TIBUpdateSQL, note that

TIBUpdateSQL is not derived from TDataSet, so the DataSet

parameter of the originating component's "OnUpdateRecord"

event handler will not be of any help to you.

5.

Note - If your SQL has parameters, you can set the value of the

parameter at run time with commands like:

DataSet1.Params[0].AsInteger=241.

DataSet1.Params.ByName[‘Department’].AsString=‘Sales’2.

5.5 TIBDataset - The self-contained Read-Only

updating component

Be sure to read the Background section before trying to understand

this section. The TIBDataset works where more than one table

needs to be updated. Where you want to update only one table,

you can use the easierTIBUpdateSQL component if you prefer.

The TIBDataset component almost identical to the TIBUpdateSQL

component (described above). The key differences are that the

TIBDataset component is derived from the TDataset. This means

the result set can be hooked up directly to a Data-Aware control

set, which means you do not use an "origniating" component. For

the "hook up", there is an additional SQL line "SelectSQL". This is

the SQL you enter for your query, and is the query that is executed

when the component's property "Active" is set to true, and is the

source of information for the data-aware controls.

5.6 TIBStoredProc - The Updating component

The TIBStoredProc component is designed to allow you to run a

Stored Procedure within InterBase.

There are two types of stored procedure.

One type returns a result set of multiple records. For this

type of Stored Procedure, use the TIBQuery, using the Stored

Procedure name in place of the table, eg:

Select ref, firstname, lastname, telephone from

StoredProcedure_GetCustomers where county='London'

1.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

22 de 42 06/04/2010 18:22

Page 23: Delphi to InterBase in 15 M

The other type returns either nothing, or single items, or a

combination of single items (such as totals) and also a

multiple result set. This is where a TIBStoredProc's power is

unparalleled and is required.

2.

To use a Stored Procedure component, you must first write the

Stored Procedure and update InterBase with it (More information?

See the Stored Procedures Chapter. Then, pop a TStoredProc

component on the form as set the following:

Fill in the Database property1.

Select the desired Stored Procedure in the StoredProcName

property (if the Procedure is not yet in InterBase, it's name

will not appear in the list of options)

2.

Fill in any input parameter details (either at design time

through the Params property or at run time using code like

StoredProc1.ParamByName{'Department'}.AsString :='IT')

3.

Format any output parameters you want formatted, through

the Params property

4.

Run the stored procedure using

StoredProc1.ExecProc

5.

Chapter 6 - SQL

SQL Outline

Background Background to SQL Metadata

ConceptsIntroduction to concepts behind

SQL

6.2 Metadata

controls

DatabaseSetting Database, Connections

and Commits

Tables The Query component

GeneratorsThe "unidirectional" Query

component

Triggers The Updating component

Indexes The SQL component

6.3 Data

controls

InsertInserting new records to the

database

UpdateUpdating records already in the

database

DeleteDeleted records already in the

database

SelectPull out a group of records in the

database

6.4 Great tips

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

23 de 42 06/04/2010 18:22

Page 24: Delphi to InterBase in 15 M

The "Where"

statement

Limiting a SQL command to affect

only restricted data

Order BySorting the result set into a

required order

Multiple tablesJoining more than one table

together

Multiple

databases

Joining tables from more than one

database together

ViewsCreating and using views to

extent joining capabilities

StatisticsGetting statistics from data within

the database

Sundry others

A collection of other SQL that

may be useful

(Cast, Upper, User Defined

Functions, Date handling)

6.1 Background

SQL is a (very simple) programming language. It is the standard

"language" to access any "grown up" database, such as InterBase,

Oracle and Microsoft SQL Server. The SQL statements can be fed

into a database in either of two ways:

From a Delphi (or any other) program - Delphi is set up to

take the strain out of working out how to send through the

statements. (More information? See the Chapter on Delphi

InterBase components).

1.

Directly into InterBase through IBConsole that comes with

InterBase.

2.

The SQL commands fall into two main categories:

the Metadata statements that control the structure of the

database and tables and

1.

the Data statements that control the data within the

database.

2.

The good news is that the entire language is made up of between

20 and 50 statements - so it is not too taxing to learn. The problem

with SQL, therefore, is not its rules, but how to apply them to make

use of the vast power of InterBase. To be of maximum help:

this guide will provide only a cursory introduction to SQL

statements. The majority of the guide will deal with concepts,

practical requirements and solutions to help you get the most

from InterBase in the minimum time. It deals primarily with

the data manipulation aspects. More extensive details of SQL

can be found in the InterBase SQL guide.

in the zip file , you should find the file Practical.SQL which

you can open in any simple text editor, such as Notepad or

Delphi. The file provides a gaggle of SQL statements which

carry out different functions we have had to generate in

applications, and which should help you deal with a number

of practical problems that can be solved by InterBase easily,

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

24 de 42 06/04/2010 18:22

Page 25: Delphi to InterBase in 15 M

once you have the answer how to do it.

6.2 Metadata SQL - some concepts

The Metadata SQL commands in InterBase control the structure of

the database, and not its data contents. You are unlikely to need

these statements when first using InterBase, so this guide is either

for the brave, foolhardy or for those who want to understand the

concepts for a future time. The commands are well explained in

manuals. There are a few tips below to help deal with a number of

practical issues:

6.2.1 The Database itself

The commands allow you to "create" and to "drop" a database (eg.

of sql: create database 'employee.gdb' and drop database.

Watch out - "drop" means delete the entire database, and

there are precious few (ie. no) controls to prevent accidental

use of this statement.

Distinguish these commands from the commands that allow

you to "connect" and "disconnect" from the database.

These commands only work for an existing database.

Connecting (eg. of sql:Connect

'machine1:c:generalInterBasedataIBDemo.gdb' user 'SYSDBA'

password 'masterkey' )is the equivalent of saying "Use the

database I am about to give you for all the commands I give

you until I disconnect".

Disconnecting (eg. of sql: Disconnect 'IBDemos.gdb') is the

termination.

One pair of commands that is clealy in the "confusing" series

are the "Commit" and "Rollback" statements. When you send

through to InterBase a series of commands, by default

InterBase treats them as being temporary pending a call to

Commit (eg. of sql: Commit) or Rollback (eg. of sql:

Rollback). If you Commit explicitly (or if you call it indirectly

either by using from within Delphi a TTransaction component

to StartTransaction and/or CommitTransaction, or by using a

sql statement followed by a command to close the database),

the transaction will be cast in stone. Alternatively, if you call

the Rollback statement directly or indirectly, the transaction

(or all transactions since the last commit or rollback

command) will be reversed and eliminated from the database.

6.2.2 Table control

You can create or alter a table (eg. of sql : Create table

WebCounter (ref integer, visit_date date, visitors_ip_address

string); - remember the semi-colon) once you have connected to

the database.

You can drop (ie. delete, along with all its data - again, no

warnings, so be very careful ) the table (eg of sql: Drop table

WebCounter ) or, alter the table (eg of sql : Alter table

WebCounter add column Page_visited varchar(60) default

'HomePage'; or Alter table WebCounter drop Page_visited; ).

This is invaluable if you want to add a column to a table you

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

25 de 42 06/04/2010 18:22

Page 26: Delphi to InterBase in 15 M

have already set up, or drop it.

If you want to change a column (eg. a column with a

reference as an integer to a reference as an integer), you

first need to create a new "temporary" column, transfer all

the data from the "old" to the "temporary" column, drop the

"old" column, add the "new" column you want to create, copy

the data from the "temporary" column to the "new" column,

and then drop the "temporary" column. Easy, isn't it!

When modifying a table, you may find that you are not permitted

to "drop" a column.

If a column is used in a stored procedure, or a calculated

field, the column is labeled as "having a dependency".

You will have to delete all the "dependencies" before you can

delete a column - then re-enter the dependencies you have

just created. This is a good reason to get the table structure

right before you create large numbers of dependencies (if you

can).

There are some other Metadata statements that are useful.

6.2.3 Generators

A Generator set (eg. of sql : CREATE GENERATOR VISIT_GEN; or

SET GENERATOR VISIT_GEN TO 1; or DROP GENERATOR

VISIT_GEN; ) is an InterBase mechanism to generate a number

count.

You can set it to, say, 1. Each time you then call the

Generator, InterBase tells you what the current number is

and then increases if for you automatically.

To call the Generator, you will probably want to set up a

simple stored procedure that you can call either from

InterBase or from a Delphi program (eg. of sql : CREATE

procedure NEW_VISIT RETURNS (NEW_REF integer) AS

BEGIN NEW_REF=gen_id(visit_gen,1); END^ - note the

strange syntax of semi-colon and ^ symbol. See the

explanation of importing SQL scripts into InterBase for an

explanation).

You can then get the next number in a sequence by calling

the stored procedure New_visit, and the new reference will

be returned in the output parameter "new_ref".

6.2.4 Triggers

A Trigger set (eg. of sql : Create trigger set_emp_no for employee

before insert as begin new.ref=gen_id(employee_gen,1); end^ )

instructs InterBase to carry out the statements in the Trigger

statement automatically (ie. without be called explicitly) every time

data in the database is updated. The example statement will set the

"ref" field in a record immediately before it is inserted to the table

"employee", with the next value in the generator "employee_gen" .

The Trigger set allow you to set up automatic procedures

either before or after any of an insert, update or delete to a

table. Vastly useful if you want to force a series of updates on

the basis, say, of a delete. Hugely frustrating if you also want

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

26 de 42 06/04/2010 18:22

Page 27: Delphi to InterBase in 15 M

use the new reference number just created within the Delphi

program that set the Trigger in motion. For this reason, using

Triggers to create unique reference numbers may be less

preferable than calling a stored procedure to return the new

generator number, and including the new reference number

with the other information of the record that is to be inserted

to the table.

A warning about Triggers - the "rollbacks" do not work quite

as you might expect. Generators, for example, will not be set

back to their earlier value, even within a rolledback

Transaction series.

6.2.5 Indexes

An index set (create and drop) is used to create indexes to speed

up searching and ordering by the indexed column. (eg. of sql:

Create unique ascending index SurnameX on person (lastname,

firstname, password); or Drop index SurnameX; )

If an index is unique, you can not enter a second record with

the same details as the first. Useful if you want to restrict

entries to just one, say, password.

Breaching this rule will be fed back to a program as an error

message which you will have to trap in Delphi if you want to

provide a graceful message to the program user. In certain

situations, therefore, you may prefer to check for the

existence of a particular record from within Delphi before

passing the record through to InterBase to update.

6.3 Data manipulation - SQL

6.3.1 Insert

You insert a record to an InterBase table (or tables) with the Insert

command (eg. of sql: INSERT INTO Nominal_Code (ref,nl_Code,

nl_Name, BalanceSheet_Category,Report_Category) VALUES (1,

100, 'Shares', 'b', 'fa'); ).

6.3.2 Update

You update a record that already exists within an InterBase table

(or tables) with the Update command (eg. of sql: UPDATE

employees SET new.salary=old.salary*1.1 ). With the update

statement, you would usually want to control the situations where

you update a record, such as update salary only where the

employee has been awarded a "satisfactory" rating or more. For

control over whether you carry out one Update command

depending on whether a given circumstance is met, see the

explanation of the Where statement.

With other update statements, you want even more control using

an IF statement, such as updating a stock record if a stock item has

been ordered from a customer and can be fulfilled, or inserting a

stock re-order item for a supplier in another table if the customer

order can not be fulfilled. To use the more precise control of an IF

statement where you want to select from more than one action in

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

27 de 42 06/04/2010 18:22

Page 28: Delphi to InterBase in 15 M

different circumstances, you would need the facility of grouping a

number of SQL statements together using a Stored Procedure.

6.3.3 Delete

You delete a record that already exists within an InterBase table

(or tables) with the Delete command (eg. of sql: DELETE from

employees). WARNING! This command deletes all records in the

table employees, and there are no warnings. With the delete

statement, you would usually want to control the situations where

you delete a record, such as delete a record from the employees

table only where the employee reference is the given number. For

control over whether you carry out one Delete depending on

whether a given circumstance is met, see the explanation of the

Where statement.

With other delete statements, you want even more control using an

IF statement, such as deleting a fulfilled sales order if the order has

been copied to the archive file, or doing the archive if not and then

deleting the record. To use the more precise control of an IF

statement where you want to select from more than one action in

different circumstances, you would need the facility of grouping a

number of SQL statements together using a Stored Procedure.

6.3.4 Select

The Select statements are very powerful, and there are a few more

things you may want to achieve, ranging from the simple to the

very advanced.

You pull out a record set from within an InterBase table (or

tables) with the Select command (eg. of sql: SELECT ref, first,

last FROM employees ).

1.

You specify the fields you want to see (such as ref, first and

last in the example). If you want all fields, you can use the '*'

character (eg. of sql: SELECT * FROM employees; ).

2.

On occasions, you want to pull out a field, but report it in a

more user friendly way. You can achieve this using the "AS"

word (eg. of sql: SELECT first, last AS surname FROM

employees; - this will report the result set with all first names

headed as "first" and all last names headed as "surname").

3.

You may also want to join fields together into one field, such

as report a name as the merging of "first" and a space and

"last". You can achieve this using the '||' characters (eg. of

sql: SELECT ref, first || ' ' || last AS FullName, salary FROM

employees; ). We have found this facility particularly useful

when creating a result set that will be displayed within an

Internet application, where you want a field in the result set

to be a link to, say, a document or image. You can achieve

this effect by pulling out a column, say, surname, which

merges the html with the database fields (eg. of sql: SELECT

first, '<a href="http://webserver/application.exe

/employeelink?Ref=' || ref || '>' || last || '</a> AS surname

from employees; ).

4.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

28 de 42 06/04/2010 18:22

Page 29: Delphi to InterBase in 15 M

With the select statement, you would usually want to pull out only

certain records, such as select all records from the employees table

where they are in a given department. For control over the content

of selected records depending on whether a given circumstance is

met, see the explanation of the Where statement.

6.4 Great SQL tips

6.4.1 Where

The data manipulation sql set (insert, update, delete and select) all

work in conjunction with the "where" clause. The "where" clause

allows you to limit the sql command to doing just what you tell it to

do. An example is selecting out all records from employees, but

only if the employee is in the IT department, or updating all

salaries, but only where the employee has been evaluated as

"satisfactory or better".

The "where" clause within the SQL command allows you to

compare any field of any table with a given value. The value

can be a number, a string, a date or another field. The

comparison can be=, <, > or various others (eg. of sql :

select ref, first, last, salary, department where

department='IT' and salary > 125000 or update employees

set new.salary=old.salary + 55000 where department='IT'

and old.salary < 95000 ) ).

1.

If you are comparing strings, you often want to use a

Wildcard character ("*" in windows). The InterBase

equivalent is '%' (eg. of sql: select ref, first, last, salary,

department where last like 'Smi%'; to pull out anyone with

the Surname starting with Smi and followed by anything,

such as Smith, Smithe, Smile ect.) You can also use the '%'

before a letter series (eg. of sql: SELECT ref, first, last,

salary, department FROM employees WHERE department like

'%IT%'; - this would pull out any department with IT

anywhere in the string). Note that you have to use the LIKE

word. Using the "=" symbol would not work, because

InterBase would be looking for the character string that was

exactly equal to '%IT%' (ie. the '%' would be treated as a

character instead of a wildcard)

2.

You can use the AND word to limit the result set to those that

meet both (or all) of the AND statements (eg. of sql: SELECT

* FROM employees WHERE department='IT' and salary

<=90000 and salary >=20000; )

3.

You can also use the OR word to expand the result set to

those that meeting any of the OR statements (eg. of sql:

SELECT * FROM employees WHERE (department='IT') OR

(salary <=90000 AND salary >=20000); ).

4.

Note where you mix both the OR word and the AND word that

you should use brackets to be clear about what you intend.

Each statement within the bracket is evaluated before any

statement outside a bracket. If the statement in the example

above has been without brackets (SELECT * FROM employees

5.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

29 de 42 06/04/2010 18:22

Page 30: Delphi to InterBase in 15 M

WHERE department='IT' OR salary <=90000 AND salary

>=20000;), InterBase would not have know whether the

statement meant pull out everyone within the IT department

and also pull out anyone with a salary between 20K and 90K

(as intended in the example) or SELECT * FROM employees

WHERE (department='IT' OR salary <=90000) AND (salary

>=20000);, which is everyone who is either in the IT

department or who has a salary less than 90K, but who also

must have a salary > 20K. The latter example would preclude

people in the IT department who earn less than 20K, which is

clearly not intended.

You may want to compare with one value does not equal

another. There are several alternatives, but the one method

that we have found infallible is to use the NOT word in front

of the statement to negate (eg. of sql: SELECT * FROM

employees WHERE not (department like 'IT%' ); ). If you try

another method (eg. WHERE department <> 'IT') within a

larger SQL command, and items do not get reported as you

would expect, remember the slightly uncomfortable solution

above.

6.

There are (many) times where you would want to use

parameters for the comparison values. This would allow you

the facility to set up a SQL statement which you could amend

at run time (eg. which does not work: SELECT * FROM

employees WHERE salary > :salary ; ). You would want to be

able to "invoke" the select command substituting the :salary

parameter with, say, the amount input by a user. To achieve

this result, can use two alternatives. Either set up a Stored

Procedure, which does take parameters, or generate the SQL

within Delphi at run time using one of the InterBase

components.

7.

In all the above examples, we have compared a field with a

fixed value. You can also compare the value with another

field within the database. You may want to select all sales

where the customer's county is different from the county of

the department who serves that customer (eg. of sql: SELECT

Customers.Ref FROM Customers, Departments WHERE

Customers.Department_ref=Departments.Ref AND not

(Customers.Postcode=Departments.County); ) . This example

joins two table together, for which you may want to see SQL

: Multiple Tables

8.

A very powerful extension to comparing a field with another

field is the ability to compare a field with a result set from

another sql command (what?!?). Say you wanted to select all

records from employees in the IT department where the

salary was less than the maximum salary being paid to a

Secretary. The WHERE clause can compare the Salary of the

employee with the result set of a separate select statement

that pulled out the maximum salary of an employee where

the department was 'Secretary' (eg. of sql: SELECT ref, first,

last FROM employees WHERE department='IT' AND salary < (

SELECT max(salary) FROM employees WHERE

department='Secretary') ;). In this example, the bracketed

SELECT statement returns a single result. (How? See Getting

Statistics from the Database). A quick warning - if the

9.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

30 de 42 06/04/2010 18:22

Page 31: Delphi to InterBase in 15 M

sub-select statement is complicated or, itself, uses another

sub-set, this can be a hugely time consuming process. The

solution, if you find the time delay is unacceptable, is to use

Stored Procedures

Another very powerful extension to comparing a field within

another field, is the ability to compare a field if it is within a

result set of another SELECT statement, using the IN word.

Say you wanted to pick out all accounts that were within the

profit and loss account, and the profit and loss accounts were

recorded in a separate table. The WHERE clause would

compare the Account_ref of the accounts with the list of

Account_refs from the master table that were profit and loss

items (eg. of sql: SELECT sum(account_value) FROM

accounts WHERE account_ref IN (select account_ref from

Accounts_Master where Account_type='Profit and loss'); ). A

quick warning - if the sub-select statement provides a long

result set, this can be a hugely time consuming process. The

solution, if you find the time delay is unacceptable, is to use

Stored Procedures

10.

The "Where" statement applies equally to the Update, Delete

and Insert statements.

11.

There are a number of other comparators that can be fun,

such as "Starting with", "Containing" and others. These are

explained in more detail in the InterBase SQL manuals.

12.

6.4.2 Order by

You sort a result set into a desired order with the Order by

statement.

You can Order by any field or fields within the original table

(eg. of sql : SELECT * FROM employees WHERE

department='IT' ORDER BY last; )

1.

You can Order by more than one field at a time (eg. of sql:

SELECT * FROM employees ORDER BY last, first; ).

2.

You can select restricted fields, and order by a field that is

not displayed, if you ever find this to be of benefit (eg. of sql:

SELECT ref, first FROM employees ORDER BY last; )

3.

The default sort order is to sort in ascending order, but you

can define it as descending (eg. of sql: SELECT * FROM

employees ORDER BY last desc, first asc; - where desc is

short for descending and asc is short for ascending)

4.

If you have defined an index which puts a result set in the same

order as the Group By statement, InterBase will automatically

detect this and will use the index to speed up the search and sort.

You can not use the name of the index within the Group By

statement(!)

6.4.3 Multiple tables

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

31 de 42 06/04/2010 18:22

Page 32: Delphi to InterBase in 15 M

You will often want to select data which involves more than one

table at a time. You may have data in two tables which you want to

combine in one report. An example is where you keep employee

details in one table, and address of everyone on another table, and

you want to report the names and address of all employees.

To use multiple tables, you can refer to them in the SQL

statement. The tables must be "joined" in a logical way.

Within an Employees table, for example, if the address is not

stored directly in the Employees table, then there must be a

reference in the Employees table to the record in the Address

table, to be able to match the records. The Select statement

must link the two tables with the "WHERE" statement. (eg. of

sql: SELECT employees.first, employees.last,

address.address1, address.address2, address.county,

address.postcode FROM address, employees WHERE

employees.address_ref=address.ref; ).

1.

You can create shorthand for the full name of the table to

save typing, by "defining" the shorthand immediately

following the table's name (eg. of sql : SELECT e.first, e.last,

add.address1, add.address2, add.county, add.postcode FROM

address add, employees e WHERE

employees.address_ref=address.ref; )

2.

One word of warning - when you "join" tables (as above),

InterBase dumbly does what you instruct. If there is a unique

reference within the address table, then there will only ever

be one record from the address table matched with any one

employee record (since the employee record can not have

more than one Address_ref in its Address_ref field). But, if

you ask InterBase to join two tables where there can be

many matches for each record, you will get a huge number of

records returned.

If, for example, you had "joined" the tables with the

statement "select * from address, employees WHERE

employee_ref < address_ref", then InterBase would have

returned a result set whose fields were every field from both

the address and the employee table. The number of items in

the result set would have been huge. InterBase would start

with the address table. It would then look at the first

employee record and see if the condition were matched. If so,

the combined record would be added to the result set. Then,

with the same address record, it would then look at the next

employee record. Again, if the condition were satisfied, the

combined record would be added to the record set. And so on

until the end of the employee table. At this point, there may

be several hundred records. But InterBase would only have

completed the first record of the Address table. It would then

carry out the same process with the second address record,

by which time another few hundred records may have been

added to the result set. Then InterBase would have gone on

to the third address record, and then the fourth and so on,

until the end. If there were several hundred records in both

the Employees and the Address files, it is easily conceivable

the result set would have exceeded half a million.

The symptom of an excessive join is InterBase taking several

3.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

32 de 42 06/04/2010 18:22

Page 33: Delphi to InterBase in 15 M

minutes to several hours to process the query and perhaps,

before it is able to finish, running out of memory. The

solution is to check the SQL statement by trying to reperform

the computer logic, to ensure that the join only ever matches

one record in one table with one record in the other table,

unless you specifically want there to be a many-to-one

relationship.

The "join" above is known as an "inner join" because it

returns only records that are in BOTH tables. This means that

a record in the employee table that has a matching record in

the address table will be reported, but a record in the

employee table without a matching record (such as the

employee's address has not yet been entered to the system),

is not reported.

There are many times where you want to report all records in

one table, and the only the matching information from the

other table. An example would be reporting all work in

progress and, if an invoice has been raised, including the

invoice information, but still reporting the work in progress

even if the invoice has not been raised.

The join that achieves this is an "outer join". Inconsistently,

the outer join requires you to use an additional word "on" to

define the linking reference fields, in place of the "where"

clause in the examples to date (eg. of sql: SELECT wip.ref,

wip.job_name, wip.value, inv.amount FROM

work_in_progress wip LEFT OUTER JOIN invoices inv ON

inv.wip_ref=wip.ref WHERE wip.completed_flag='False'; -

note using joins does not prevent the use of the "WHERE"

clause, but it does require the ON clause ). The word LEFT or

RIGHT is used to tell InterBase which of the two tables is the

base for which all records will be reported even without a

match. In the example, the work_in_progress table is on the

LEFT of the statement, and this is the table that you want to

be reported in full, even where there is no match.

4.

The OUTER JOIN statement is explained above. The prior

examples of inner joins use the WHERE clause to achieve the

match. You can also achieve the same result using the INNER

JOIN statement (eg. of sql: SELECT e.first, e.last,

add.address1, add.address2, add.county, add.postcode FROM

address add, employees e ON employees.address_ref INNER

JOIN address.ref; )

5.

There are often occasions where you will want to "chain"

more than two tables together. You can chain joins

conceptually joining two tables together, then joining the

result set with the third table (and so on if you have more

than three tables to join). This is useful where you are

reporting information from more than two tables in one

report, such as reporting details from our ebooks site which

reports the name of a reader (from the address table), the

date of the purchase (from the order table) and the name of

the book bought (from the book table) (eg. of sql : SELECT

p.ref,p.first, p.last, o.orderdate, d.bookref, b.booktitle FROM

address p INNER JOIN orders o ON o.personref=p.ref LEFT

OUTER join order_details d ON d.orderref=o.ref LEFT OUTER

6.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

33 de 42 06/04/2010 18:22

Page 34: Delphi to InterBase in 15 M

JOIN books b ON b.ref=d.bookref order by last, orderdate; - if

you want to use a further WHERE clause, it comes after the

final ON statement, irrespective of which file the restrictions

apply to).

There are often occasions where even this level of

combination is inadequate for what you want to achieve.

Although conceptually the second join works on the result set

of the first join, there is very little manipulation you can

carry out prior to the second join. This can be too limiting. An

example of the sql constraints are where may need to get the

sales totals of each salesperson on which to calculate

commission, you need to report the result in descending

order of sales totals. There is no sql command you can use to

Order on the results of a calculated amount. You will come

across several other circumstances where you need to carry

out a function (such as selection, grouping, sorting) on the

results of another group.

The solution is to use Views or Stored Procedures, which you

are then able to chain together to your hearts content.

6.4.4 Multiple databases

Joining data between two tables all held within the one

database is useful. You may find the need to join data held in

two or more databases.

All rules that apply to joining tables from a single database

apply equally to joining tables from two separate databases.

The additional issues that are explained below relate to the

need to "login" to both databases which may have different

usernames and passwords, and the syntax SQL requires to

understand to look in the two databases.

The connection issue is simple. For each database you

want to connect to, you must enter the username and

password. One method to achieve this within a single

sql command is to achieve the connections within the

Delphi program. Create (or drop onto a form) two

separate Delphi InterBase TIBDatabase components,

and fill in the details and, if appropriate, the username

and passwords. (How? See TIBDatabase components.)

1.

The SQL syntax requires the databases to be within

quotation marks, preceded by a colon (eg. of sql:

SELECT own.NAME, own.OWNER FROM

":invDB:OWNER" own, ":crownDB:COMPANY" co

WHERE co.REF=inv.COMP_REF - where invDB and

crownDB are the TIBDatabase names allocated in the

Delphi program.) To complete this example, fill in a

TIBQuery component, filling in the SQL in the SQL

property of the TIBQuery component, and the query is

ready to be called by your Delphi program.

2.

6.4.5 Views

7.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

34 de 42 06/04/2010 18:22

Page 35: Delphi to InterBase in 15 M

Views are sql statements that are "frozen" into a procedure

within InterBase. Typically, but not always, a View will return

a result set. Once set up, the view can then be called and

used as if it is a Table. There are some restrictions (see

below), but the value comes from the ability to carry out a

reasonably complex SQL statement within a view, and then to

use the View as if it were a table, against which you can

perform a separate SQL statement.

Views are a quirk of InterBase, so they have to be set up

within InterBase. You can set them up as follows:

Create a SQL script file, which you will be able to use to

"import" the view into InterBase (Example? See the

downloadable file">http://www.softwaredesign.co.uk

/download/DelphiToInterbaseSQL.zip>file Tables.SQL,

and look out for the "Create View" statement

1.

Create the View, which attaches a basic SQL statement

to the instruction to InterBase to file the statement

within its Views Metadata (eg. of sql: CREATE VIEW

Full_Name (iRef integer,iDepartment varchar(30)) AS

SELECT ref, first || ' ' || last as EntireName, AddressRef

FROM employee WHERE ref >=:iRef and

department=:iDepartment;- where the View is called

"Full_Name" and two input parameters have been

defined as "iRef", which is an integer and iDepartment

which is a string. The output is the result set generated

by the "Select" statement.)

2.

Once a View has been created, it can be used from any

SQL statement (from InterBase or from a Delphi

program as described in earlier sections) as if it is a

Table (eg. of sql: SELECT * FROM Full_Name(27, 'IT')

ORDER BY ref desc; - note that the View has an input

parameter, so when calling it, you have to include the

parameter after "Full_Name" in brackets. If there had

been no input parameters, there would have been no

brackets after "Full_Name".

3.

You can create a view which uses the result set of

another view (and so on indefinitely). As with any SQL

command, if the first view has parameters, the second

view must provide the parameter call syntax (eg. of sql

: CREATE VIEW Addressed_Full_Name (iRef

integer,iDepartment varchar(30)) AS SELECT * FROM

Full_Name(:iRef, :iDepartment), Address WHERE

Address.ref=Full_Name.AddressRef ORDER BY

Full_Name.EntireName; - this is called as any other

view. When InterBase hits the "table" Full_Name within

the SQL statement, it knows this is a view, the second

view is put on hold and the first view is run before

processing of the second view resumes.

4.

Views have a couple of limitations - if the limitations

prevent you from doing something you need to do, you

should almost certainly be using Stored Procedures.

(How? See the Chapter on Stored Procedures). One

limitation relates to using Views to update, insert or

delete data. Views can be used for this purpose, but

5.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

35 de 42 06/04/2010 18:22

Page 36: Delphi to InterBase in 15 M

generally only if there is no ambiguity in the SQL

commands to InterBase. If you use a view simply with a

SQL command to Update a record, using a where

statement, the update should work fine. However, if

your view has changed the information from the form

of a basic table, or if it is no longer clear which table

the information came from, then you are prohibited

from using a View for this purpose. For more details,

see the InterBase manuals. Another limitation is the

inability to define an output parameter.

6.4.6 Statistics

Reporting statistics from data within the database is easy.

Used in conjunction with Views and/or Stored Procedures,

they provide you with the ability to provide almost any report

that may be requested.

The basic statistics come from a Select statement, using

words like "Sum", "Count" and "Avg" (eg. of sql:

SELECT count(ref), avg(VAT), sum(Sales_Value) FROM

sales; - this provides the total number of transactions,

the average of the VAT and the sum of the

Sales_Value.)

1.

The above example provides one total only for the

entire database. If you wanted to group a number of

like items together and provide the sum for each of the

groups, you can achieve this by using the GROUP BY

statement. For example, you may have a table of Sales,

and you want to know how much are the sales by

product line (eg. of sql: SELECT product_line,

sum(sales_value) FROM sales GROUP BY product_line;

).

2.

You can also get sub-totals of sub_totals using the

same technique. If you wanted to group the total sales

value of each product lines sold each sales person, you

can do so (eg. of sql : SELECT sales_person,

product_line, sum(sales_value) FROM sales GROUP BY

sales_person, product_line; .)

3.

You can use any normal SQL statements within the

statements, such as ORDER BY, and WHERE clauses.

4.

If you wanted to use the results of the Statistics for a

further action, such as sorting the results by

descending value of the sum of the sales_value, you

will fund you are not permitted to do so within the one

sql statement. The simple solution is to create a View

with the statistics, then use the View within a second

SQL statement to carry out the action that you wanted.

(How? See Views)

5.

6.4.7 Sundry

There are several other functions that may help you. They

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

36 de 42 06/04/2010 18:22

Page 37: Delphi to InterBase in 15 M

include:

If you want to change one datatype to another, use the

Cast function. For example, you may want to convert a

reference defined as an integer to a string to

consolidate within HTML (eg. of sql : SELECT cast(ref as

varchar(20)) FROM sales WHERE Payment_flag='False';

)

1.

String comparisons are case sensitive. Programmers

and Users are not always consistent when obtaining or

entering data (eg. Names) that may be used within

case sensitive comparisons (eg. passwords). InterBase

has a function UPPER, which converts a field into its

Upper case equivalent. This allows comparison of the

upper case of one field with the upper case of the other,

and removes the case sensitivity problems, if this is

what you want to do (eg. of sql : SELECT ref, name

FROM employee WHERE

upper(first)=upper(:InputParameter); ). Curiously,

there is no LOWER equivalent in InterBase.

2.

InterBase has a very limited number of functions (such

as CAST and UPPER). There are many occasions you

would want these functions extended (such as stripping

out blanks, selecting out the left three characters of a

string, using a MID function, formatting Currency

strings and SIN functions). There are a large number of

functions that perform these tasks, and which are

available free. Check out the InterBase manuals for

External Functions which will give you a pointer to

where to get the suite of External Functions (also called

User Defined Functions), and how to instruct InterBase

where to find the code for them. When you have

"imported" an External Function, you can use it in the

same way as UPPER and CAST above, using parameters

where required by the Function (eg. of sql : SELECT

F_FixedDecimalPoint(PRICE,2) FROM Sales; - where

FixedDecimalPoint is the imported user defined

function, Price is a field in the Sales database, and "2"

is the number of decimal places to which the number

should be rounded).

3.

Date handling in InterBase is primitive. You may have

to use the US format for date entry (ie. mm/dd/yy,

instead of the UK configuration of dd/mm/yy), when

entering the date as a string. InterBase stores the Date

as DateTime. This causes huge problems when trying to

pull out transactions on, say, a particular day, since the

date stored (which includes the time tagged to the

end), will not necessarily equal the date you have input

for comparison. There are several solutions to date

problems. One is to specify time consistently when you

enter a date (messy), another is to use a User Defined

Function to strip out the time element of a date field

(for which you need the UDF and you need to import

it), another is always to use dates within a range (such

as 'DateField >=1/1/2000 00:00 and DateField

<='1/1/2000 23:59', in place of 'DateField=1/1/2000').

4.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

37 de 42 06/04/2010 18:22

Page 38: Delphi to InterBase in 15 M

Chapter 7 - Stored Procedures

This Chapter is written on the basis that the InterBase SQL

file from this zip file (StoredProcedures.SQL ) are open within

a simple text editor (such as Notepad or Delphi). If you read

the guide in conjunction with the SQL files, the points below

should be simple to follow.

7.1 What you can do with Stored Procedures

Stored Procedures are functions that are written and stored

in InterBase, that carry out a series of SQL commands. They

are fast, powerful and can be used with both input and output

parameters.

You can define a Stored Procedure to return both a

Result set (eg. a list of sales items), and also some

output parameters (eg. the total of the sales items

output). Used in conjunction with the

TIBStoredProcedure component, you have access to

both the Result set and also to the output parameters.

1.

If a Stored Procedure returns just a result set, you can

call it from either Delphi or from InterBase, as you

would any SQL statement, using the Stored Procedure

as if it were a table. If there are input parameters, you

put the parameters in brackets immediately after the

Stored Procedure name (eg. of sql : SELECT * FROM

sp_Sales_Report('1/1/2000','1/31/2000','IT');- where

the Procedure is called "sp_Sales_Report" and three

input parameters have been defined (a start date, and

end date and a Department name). The output is the

result set generated by the "Select" statement.)

2.

Alternatively, you may use a TIBStoredProcedure

component from Delphi, or the "Execute Procedure"

command InterBase. If there is not a result set, but a

single output parameter (or parameters), or if the

Stored Procedure does not return any results (eg. on

Inserting or updating a record), you must use the

TIBStoredProcedure component from Delphi, or the

"Execute Procedure" command from InterBase.

3.

7.2 The Syntax

If you get the Stored Procedures syntax wrong, there may be

two consequences. Firstly, the Stored Procedure may be

imported successfully into InterBase, but fail to operate

properly. The second is that the Procedure may not be

imported successfully. There are few programs that will cause

you so much frustration as you may find trying to work your

way through the error messages returned when a Stored

Procedure fails to import successfully. To save yourself a vast

amount of time and frustration, you may want to read the

following Syntax concepts carefully.

You must create a SQL script file. (How? See Creating a1.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

38 de 42 06/04/2010 18:22

Page 39: Delphi to InterBase in 15 M

SQL script)

Creating a procedure uses the "Create Procedure"

command. If you have already successfully created a

procedure and you want to amend part of it, change the

command to "Alter Procedure", then use exactly the

same code as if you had just deleted the procedure and

you were now creating it from scratch.

2.

Once the script is in place, the Stored procedure has a

number of distinct parts:

Input parameters, if there are any, come within

brackets immediately after the name of the procedure.

Each Input parameter must have a data type, and each

parameter is separated by a comma. The last parameter

is not followed by a comma, but by the closed bracket

sign. (eg. of sql : CREATE PROCEDURE

sp_Salespersons_summary (Salesperson_ref integer,

Start_date date, End_date date) - Note: no semi colon

goes here

1.

Output parameters, if there are any, start with the

RETURNS word, and have the same rules as the Input

parameters. Note that the Output parameter must not

have the same name as the Input parameter. If there is

any possible conflict, use any resolution technique you

are comfortable with, such as preceding the input

parameters with the letter "i" (eg. of sql : CREATE

PROCEDURE sp_Salespersons_summary

(iSalesperson_ref integer, iStart_date date, iEnd_date

date) RETURNS (oSales_value decimal(10,2) , oName

varchar(50) )- Note: no semi colon anywhere in sight

2.

Next you must place the word "AS", irrespective of

whether you have defined input and/or output

parameters. (eg. of sql : CREATE PROCEDURE

sp_Archive_Sales AS ...)- Note: no semi colon

anywhere in sight. If there are input and/or output

parameters, they go between the word PROCEDURE

and AS

3.

The next part is the place where you can define a

variable for use within the stored procedure. Define

each variable with its datatype. Again, be careful to

avoid name conflicts. Each variable is defined

independently of another (eg of sql: CREATE

PROCEDURE sp_Archive_sales AS declare variable vRef

integer; declare variable vSalesTotal numeric(15,2);

declare variable vCustomerRef integer; - Note that

there is a semi-colon after each declared variable.

4.

Then comes the part where the data set is Selected, on

which the Stored Procedure does its work. It comes

within a BEGIN .. END statement. Since there are other

Begin..End pairs coming, this guide refers to this BEGIN

.. END pairing as the Procedure's Workframe. The

Workframe's "END" word would be followed by a

semi-colon to denote cessation of the overall Stored

Procedure, but for the fact that there are semi-colons

5.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

39 de 42 06/04/2010 18:22

Page 40: Delphi to InterBase in 15 M

within the Stored Procedure which are used to denote

the end of a statement. So there is a separate symbol

used to show that the Stored Procedure has terminated,

which you define in your SQL script file. The example

files use the symbol '^', but another symbol commonly

used to denote the end of a Stored Procedure is '!!' (eg.

of sql: CREATE PROCEDURE sp_Archive_Sales AS

BEGIN END^ - This stored procedure does nothing, but

is valid.)

The concept of the WorkFrame (as defined in the preceding

paragraph) is really very powerful. Once you have defined

the input, output and variable parameters, you can then fill

in any manner of SQL statements you desire. The procedure's

WorkFrame are typically separated into two distinct parts

The first part (which is optional) selects out a set of

records that the Stored Procedure can then work on,

one record at a time. One of the key problems with

basic SQL statements it that they issue commands

which work at table level, and they are not capable of

working at record level. With conventional SQL,

therefore, you are able to carry out or not an action on

a record depending on the "Where" conditions, but you

are unable to carry out a different action depending on

the status of the record itself. The first part, therefore,

defines the data which the second part will work on,

one by one.

The Syntax should be familiar by now, but with some

modifications. To instruct InterBase that the Procedure

will work on the data one at a time, the word "FOR"

precedes the Select statement. The Select statement is

then identical to any other Select statement, with the

ability to use input parameters, by preceding the name

with a colon to indicate it is a parameter ( eg. of sql:

FOR SELECT Ref, Name FROM employees WHERE

ref=:iRef - where :iRef is an input parameter).

But to allow the Procedure to work on each record

individually, you have to put the data selected for that

record ("ref" and "name" in the above example), into a

variable that you can refer to later in the Procedure.

The variable can be either an output parameter or a

declared variable. If you put the data into an output

variable, it will be included within the record written as

part of the result set, when the Procedure has finished

processing the record. If you do not put the data into

an output variable, you will have to do so later on in

the Procedure, or "null" data will be written. To put the

result of each record into a variable, use the INTO work

(eg. of sql CREATE PROCEDURE

sp_Salespersons_summary (iRef integer) RETURNS

(oRef integer, oName varchar(50) ) FOR SELECT Ref,

Name FROM employees WHERE ref=:iRef into :oRef,

:oName - Note, no semi-colon anywhere in sight in this

section so far, although there would have been if an

internal variable had been declared)

1.

The second part (which is mandatory if there is a 'FOR2.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

40 de 42 06/04/2010 18:22

Page 41: Delphi to InterBase in 15 M

SELECT' statement in the first part) does something

with the data selected above, one record at a time.

The section starts with the word DO, and has its own

"begin .. end" pair. Note that this pair does not have a

semi-colon to denote its termination.

Within the "begin .. end" pair, you can then put in as

many or as few sql statements as you desire. There are

also a few simple programming statements you can use

(such as vSalesTotal=0; ). Each programming

statement is terminated with a semi-colon.

Parameters and variables are accessed with a colon in

front. Watch out for one pitfall. Sometimes a variable

can not be accessed if you precede it with a colon,

whereas at other times, it can not be accessed without

the colon in front(!), such as vSalesTotal=:vSalesTotal

+ 10; ). We have found that trial and error has always

worked, once you are aware of the potential problem.

Each statement can be a simple programming

statement (such as :outputTotal=:outputTotal +

:inputTransactionAmount;), or a SQL statement (such

as UPDATE assets SET num=num + :jNum, cost=cost +

:jCost, val=val + :jVal, latestDate=:latestDate where

ref=:jAssetRef; - where assets is the name of a table,

num, cost, vale and latestDate are fields in the table

assets and :jNum, :jCost, :jVal, :latestDate and

:jAssetRef are all variables into which the Select

statement placed its data.)

When the Stored Procedure has finished processing the

record from the select statement and is ready to move

onto the next, the instruction telling the Stored

Procedure to add the output data to the record set that

will eventually be available to the Delphi (or InterBase)

program, is "SUSPEND;". Note the semi-colon. SQL

statements can continue to operate subsequent to the

SUSPEND; statement, but it would seem sensible for

the SUSPEND; statement to be the last statement.

Note, too, that the SUSPEND; statement is required,

even if there has been no processing of SQL

statements, or the data selected in the SELECT

statement will not be written to the result set (eg. of

sql : CREATE PROCEDURE sp_Salespersons_summary

(iRef integer) RETURNS (oRef integer, oName

varchar(50) ) BEGIN FOR SELECT Ref, Name FROM

employees WHERE ref=:iRef into :oRef, :oName do

begin suspend; end END^ )

The Procedures.SQL file is intended to provide several

examples of use of Stored Procedures in a practical

environment. The Procedures can almost all be written

better, but they are designed to illustrate concepts and use of

Stored Procedure.

Chapter 8 - Guide updates and limitationof liability

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

41 de 42 06/04/2010 18:22

Page 42: Delphi to InterBase in 15 M

This guide has been inspired by the move of InterBase

towards Open Source. InterBase appears to have a strategy

to make InterBase to Linux what DB was to DOS and the

Paradox format/BDE was to Delphi. It is already a very

powerful, efficient and compact program. The trend towards

Open Source hold out the promise of even more power and

ease of use for Developers, and continuing adaptation to

developments in IT.

8.1The purpose of the guide

InterBase is available on the Linux. Delphi is being ported (as

at 1 July 2000) to the Linux platform.

The combination of Delphi and InterBase is a powerful one.

The combination may well be the first mature offering for

mass development within the Linux platform. The purpose of

this book is to reduce the learning curve for anyone wanting

to have access to this powerful and free resource.

8.2 Updates and correction of errors

If any readers find errors, or if there are any areas of

InterBase or Delphi's interaction with InterBase that are still

difficult to fathom from the manuals that exist, for which this

guide may be useful, please email your comments to

[email protected]. This guide comes in HTML format

and is available free from IBPhoenix. Based on comments fed

through, the guide will be updated regularly and the latest

updated version will be available from www.ebooks.uk.net for

a nominal sum, under the title "Delphi to InterBase in 15

minutes" (the ebooks site itself is driven by Delphi and

InterBase).

8.3 Limitation of liability

This guide is provided within the spirit of the Open Source

initiative. No representations are made that any of the

material above is accurate or complete. No liability can be

accepted by the authors by for any errors or omissions in the

guide.

Delphi to InterBase in 15 Minutes file:///C:/Users/TECBMFRP/AppData/Roaming/Mozilla/Firefox/Pro...

42 de 42 06/04/2010 18:22