Begin declare section

Содержание

begin declare section

Description

Begins a declare section, which declares host language variables used in an EmbeddedВ SQL source file.

Syntax

Parameters

The declaration of one or more host language variables.

Examples

Example 1

Usage

A declare section must end with the EmbeddedВ SQL statement endВ declareВ section.

A source file can have any number of declare sections.

declare sections can be placed anywhere that variables can be declared. The declare section that declares a variable must precede any statement that references the variable.

Variable declarations in a declare section must conform to the rules of the host language.

Nested structures are valid in a declare section; arrays of structures are not.

A declare section can contain any number of EmbeddedВ SQL include statements.

In EmbeddedВ SQL/C routines, the Client-Library datatypes defined in cspublic.h can be used in declare sections.

In C routines, you can declare two-dimensional arrays of characters but only one-dimensional arrays of other datatypes.

When processing declare sections, the EmbeddedВ SQL precompiler ignores C preprocessor macros and #include statements. When processing EmbeddedВ SQL include statements within a declare section, the EmbeddedВ SQL precompiler treats the contents of the included file as though had been entered directly into the file being precompiled.

How to return rows from a declare/begin/end block in Oracle?

I want to return rows from a select statement within a declare/begin/end block. I can do this in T-SQL but I would like to know how to do it in PL/SQL.

The code looks a bit like the following:

2 Answers 2

An anonymous PL/SQL block, like the one you’ve shown, can’t «return» anything. It can interact with the caller by means of bind variables, however.

So the method I would use in this case would be to declare a cursor reference, open it in the PL/SQL block for the desired query, and let the calling application fetch rows from it. In SQLPlus this would look like:

If you recast your PL/SQL as a stored function then it could return values. In this case what you might want to do is create a collection type, fetch all the rows into a variable of that type, and return it:

Well, this depends heavily on your data access library.

You can return any SQL-compatible type as a parameter. This includes complex SQL types and collection types. But most libraries are simply not capable of handling Oracle’s object types.

Either way, my examples will use these object types:

When your access library can handle object types, you could simply return a list of PL/SQL objects:

If not, you could hack around it by forcing this list into a select and return its result as a cursor:

Meeting Program Requirements

Passing data between Oracle and your application program requires host variables, datatype conversions, event handling, and access to Oracle. This chapter shows you how to meet these requirements. You learn the embedded SQL commands that declare variables, declare communication areas, and connect to an Oracle database. You also learn about the Oracle datatypes, National Language Support (NLS), data conversion, and how to take advantage of datatype equivalencing. The final two sections show you how to embed OCI calls in your program and how to develop X/Open applications.

The Declare Section

You must declare all program variables to be used in SQL statements (that is, all host variables) in the Declare Section. If you use an undeclared host variable in a SQL statement, the precompiler issues an error message. For a complete listing of error messages see Oracle7 Server Messages.

The Declare Section begins with the statement

and ends with the statement

Note: In COBOL, the statement terminator is END-EXEC. In FORTRAN, it is a carriage return.

Between these two statements only the following items are allowed:

  • host-variable and indicator-variable declarations
  • EXEC SQL DECLARE statements
  • EXEC SQL INCLUDE statements
  • EXEC SQL VAR statements
  • EXEC ORACLE statements
  • host-language comments

Multiple Declare Sections are allowed per precompiled unit. Furthermore, a host program can contain several independently precompiled units.

An Example

In the following example, you declare four host variables for use later in your program. (Remember, many program examples are written in a pseudocode, which is described vi in the Preface.)

For more information about declaring host variables, see «Declaring and Referencing Host Variables» .

INCLUDE Statements

The INCLUDE statement lets you copy files into your host program. It is similar to the COBOL COPY command. An example follows:

When you precompile your program, each EXEC SQL INCLUDE statement is replaced by a copy of the file named in the statement.

You can INCLUDE any file. If a file contains embedded SQL, you must INCLUDE it because only INCLUDEd files are precompiled. If you do not specify a file extension, the precompiler assumes the default extension for source files, which is language-dependent (see your host-language supplement to this Guide).

You can set a directory path for INCLUDEd files by specifying the precompiler option

where path defaults to the current directory. (In this context, a directory is an index of file locations.)

The precompiler searches first in the current directory, then in the directory specified by INCLUDE, and finally in a directory for standard INCLUDE files. So, you need not specify a directory path for standard files such as the SQLCA and ORACA. You must still use INCLUDE to specify a directory path for nonstandard files unless they are stored in the current directory.

If your operating system is case-sensitive (like UNIX for example), be sure to specify the same upper/lower case filename under which the file is stored. The syntax for specifying a directory path is system-specific. Check your system-specific Oracle manuals.

The SQLCA

The SQLCA is a data structure that provides for diagnostic checking and event handling. At run time, the SQLCA holds status information passed to your program by Oracle. After executing a SQL statement, Oracle sets SQLCA variables to indicate the outcome, as illustrated in Figure 3 — 1.

Thus, you can check to see if an INSERT, UPDATE, or DELETE statement succeeded and if so, how many rows were affected. Or, if the statement failed, you can get more information about what happened.

When MODE=, you must declare the SQLCA by hardcoding it or by copying it into your program with the INCLUDE statement. The section «Using the SQL Communications Area» shows you how to declare and use the SQLCA.

Oracle Datatypes

Oracle recognizes two kinds of datatypes: internal and external. Internal datatypes specify how Oracle stores data in database columns. Oracle also uses internal datatypes to represent database pseudocolumns. An external datatype specifies how data is stored in a host variable.

At precompile time, each host variable in the Declare Section is associated with an external datatype code. At run time, the datatype code of every host variable used in a SQL statement is passed to Oracle. Oracle uses the codes to convert between internal and external datatypes.

Note: You can override default datatype conversions by using dynamic SQL Method 4 or datatype equivalencing. For information about dynamic SQL Method 4, see «Using Method 4» . For information about datatype equivalencing, see «Datatype Equivalencing» .

Internal Datatypes

shows the internal datatypes that Oracle uses for database columns and pseudocolumns.

When AUTO_CONNECT=NO (the default), you must use the CONNECT statement to log on to Oracle.

Concurrent Logons

The Oracle Precompilers support distributed processing via SQL*Net. Your application can concurrently access any combination of local and remote databases or make multiple connections to the same database. In Figure 3 — 2, an application program communicates with one local and three remote Oracle databases. ORA2, ORA3, and ORA4 are simply logical names used in CONNECT statements.

By eliminating the boundaries in a network between different machines and operating systems, SQL*Net provides a distributed processing environment for Oracle tools. This section shows you how the Oracle Precompilers support distributed processing via SQL*Net. You learn how your application can

  • access other databases directly or indirectly
  • concurrently access any combination of local and remote databases
  • make multiple connections to the same database

Some Preliminaries

The communicating points in a network are called nodes. SQL*Net lets you transmit information (SQL statements, data, and status codes) over the network from one node to another.

A protocol is a set of rules for accessing a network. The rules establish such things as procedures for recovering after a failure and formats for transmitting data and checking errors.

The SQL*Net syntax for connecting to the default database in the local domain is simply to use the service name for the database.

If the service name is not in the default (local) domain, you must use a global specification (all domains specified). For example:

Default Databases and Connections

Each node has a default database. If you specify a node but no database in your CONNECT statement, you connect to the default database on the named local or remote node. If you specify no database and no node, you connect to the default database on the current node. Although it is unnecessary, you can specify the default database and current node in your CONNECT statement.

A default connection is made using a CONNECT statement without an AT clause. The connection can be to any default or non-default database at any local or remote node. SQL statements without an AT clause are executed against the default connection. Conversely, a non-default connection is made by a CONNECT statement that has an AT clause. A SQL statement with an AT clause is executed against the non-default connection.

All database names must be unique, but two or more database names can specify the same connection. That is, you can have multiple connections to any database on any node.

Explicit Logons

Usually, you establish a connection to Oracle as follows:

Or, you might use

where usr_pwd contains username/password.

You can also log on automatically as shown .

If you do not specify a database and node, you are connected to the default database at the current node. If you want to connect to a different database, you must explicitly identify that database.

With explicit logons, you connect to another database directly, giving the connection a name that will be referenced in SQL statements. You can connect to several databases at the same time and to the same database multiple times.

Single Explicit Logons

In the following example, you connect to a single non-default database at a remote node:

The identifiers in this example serve the following purposes:

  • The host variables username and password identify a valid user.
  • The host variable db_string contains the SQL*Net syntax for logging on to a non-default database at a remote node using the DECnet protocol.
  • The undeclared identifier db_name names a non-default connection; it is an identifier used by Oracle, not a host or program variable.

The USING clause specifies the network, machine, and database to be associated with db_name. Later, SQL statements using the AT clause (with db_name) are executed at the database specified by db_string.

Alternatively, you can use a character host variable in the AT clause, as the following example shows:

If db_name is a host variable, the DECLARE DATABASE statement is not needed. Only if db_name is an undeclared identifier must you execute a DECLARE db_name DATABASE statement before executing a CONNECT . AT db_name statement.

SQL Operations. If granted the privilege, you can execute any SQL data manipulation statement at the non-default connection. For example, you might execute the following sequence of statements:

In the next example, db_name is a host variable:

If db_name is a host variable, all database tables referenced by the SQL statement must be defined in DECLARE TABLE statements.

Cursor Control. Cursor control statements such as OPEN, FETCH, and CLOSE are exceptions—they never use an AT clause. If you want to associate a cursor with an explicitly identified database, use the AT clause in the DECLARE CURSOR statement, as follows:

If db_name is a host variable, its declaration must be within the scope of all SQL statements that refer to the declared cursor. For example, if you open the cursor in one subprogram, then fetch from it in another, you must declare db_name globally or pass it to each subprogram.

When opening, closing, or fetching from the cursor, you do not use the AT clause. The SQL statements are executed at the database named in the AT clause of the DECLARE CURSOR statement or at the default database if no AT clause is used in the cursor declaration.

The AT :host_variable clause allows you to change the connection associated with a cursor. However, you cannot change the association while the cursor is open. Consider the following example:

This is illegal because emp_cursor is still open when you try to execute the second OPEN statement. Separate cursors are not maintained for different connections; there is only one emp_cursor, which must be closed before it can be reopened for another connection. To debug the last example, simply close the cursor before reopening it, as follows:

Dynamic SQL. Dynamic SQL statements are similar to cursor control statements in that some never use the AT clause. For dynamic SQL Method 1, you must use the AT clause if you want to execute the statement at a non-default connection. An example follows:

For Methods 2, 3, and 4, you use the AT clause only in the DECLARE STATEMENT statement if you want to execute the statement at a non-default connection. All other dynamic SQL statements such as PREPARE, DESCRIBE, OPEN, FETCH, and CLOSE never use the AT clause. The next example shows Method 2:

The following example shows Method 3:

You need not use the AT clause when connecting to a remote database unless you open two or more connections simultaneously (in which case the AT clause is needed to identify the active connection). To make the default connection to a remote database, use the following syntax:

Multiple Explicit Logons

You can use the AT db_name clause for multiple explicit logons, just as you would for a single explicit logon. In the following example, you connect to two non-default databases concurrently:

The undeclared identifiers db_name1 and db_name2 are used to name the default databases at the two non-default nodes so that later SQL statements can refer to the databases by name.

Alternatively, you can use a host variable in the AT clause, as the following example shows:

You can also use this method to make multiple connections to the same database, as the following example shows:

You must use different database names for the connections, even if they use the same SQL*Net string.

Implicit Logons

Implicit logons are supported through the Oracle distributed database option, which does not require explicit logons. For example, a distributed query allows a single SELECT statement to access data on one or more non-default databases.

The distributed query facility depends on database links, which assign a name to a CONNECT statement rather than to the connection itself. At run time, the embedded SELECT statement is executed by the specified Oracle Server, which connects implicitly to the non-default database(s) to get the required data.

Single Implicit Logons

In the next example, you connect to a single non-default database. First, your program executes the following statement to define a database link (database links are usually established interactively by the DBA or user):

Then, the program can query the non-default EMP table using the database link, as follows:

The database link is not related to the database name used in the AT clause of an embedded SQL statement. It simply tells Oracle where the non-default database is located, the path to it, and what Oracle username and password to use. The database link is stored in the data dictionary until it is explicitly dropped.

In our example, the default Oracle Server logs on to the non-default database via SQL*Net using the database link db_link. The query is submitted to the default server, but is «forwarded» to the non-default database for execution.

To make referencing the database link easier, you can create a synonym as follows (again, this is usually done interactively):

Then, your program can query the non-default EMP table, as follows:

This provides location transparency for emp.

Multiple Implicit Logons

In the following example, you connect to two non-default databases concurrently. First, you execute the following sequence of statements to define two database links and create two synonyms:

Then, your program can query the non-default EMP and DEPT tables, as follows:

Oracle executes the query by performing a join between the non-default EMP table at db_link1 and the non-default DEPT table at db_link2.

Embedding OCI (Oracle Call Interface) Calls

The Oracle Precompilers let you embed OCI calls in your host program. Just take the following steps:

That way, the Oracle Precompiler and the OCI «know» that they are working together. However, there is no sharing of Oracle cursors.

You need not worry about declaring the OCI Host Data Area (HDA) because the Oracle runtime library manages connections and maintains the HDA for you.

Setting Up the LDA

You set up the LDA by issuing the OCI call

where lda identifies the LDA data structure. The format of this call is language-dependent. See the Programmer’s Guide to the Oracle Call Interface. If the CONNECT statement fails, the lda_rc field in the lda is set to 1012 to indicate the error.

Remote and Multiple Connections

A call to SQLLDA sets up an LDA for the connection used by the most recently executed SQL statement. To set up the different LDAs needed for additional connections, just call SQLLDA with a different lda after each CONNECT. In the following example, you connect to two non-default databases concurrently:

Remember, do not declare db_name1 and db_name2 in the Declare Section because they are not host variables. You use them only to name the default databases at the two non-default nodes so that later SQL statements can refer to the databases by name.

Developing X/Open Applications

X/Open applications run in a distributed transaction processing (DTP) environment. In an abstract model, an X/Open application calls on resource managers (RMs) to provide a variety of services. For example, a database resource manager provides access to data in a database. Resource managers interact with a transaction manager (TM), which controls all transactions for the application.

Figure 3 — 3 shows one way that components of the DTP model can interact to provide efficient access to data in an Oracle database. The DTP model specifies the XA interface between resource managers and the transaction manager. Oracle supplies an XA-compliant library, which you must link to your X/Open application. Also, you must specify the native interface between your application program and the resource managers.

The DTP model that specifies how a transaction manager and resource managers interact with an application program is described in the X/Open guide Distributed Transaction Processing Reference Model and related publications, which you can obtain by writing to

For instructions on using the XA interface, see your Transaction Processing (TP) Monitor user’s guide.

Oracle-Specific Issues

You can use the Oracle Precompilers to develop applications that comply with the X/Open standards. However, you must meet the following requirements.

Connecting to Oracle

The X/Open application does not establish and maintain connections to a database. Instead, the transaction manager and the XA interface, which is supplied by Oracle, handle database connections and disconnections transparently. So, normally an X/Open-compliant application does not execute CONNECT statements.

Transaction Control

The X/Open application must not execute statements such as COMMIT, ROLLBACK, SAVEPOINT, and SET TRANSACTION that affect the state of global transactions. For example, the application must not execute the COMMIT statement because the transaction manager handles commits. Also, the application must not execute SQL data definition statements such as CREATE, ALTER, and RENAME because they issue an implicit commit.

The application can execute an internal ROLLBACK statement if it detects an error that prevents further SQL operations. However, this might change in later versions of the XA interface.

OCI Calls

If you want your X/Open application to issue OCI calls, you must use the runtime library routine SQLLD2, which sets up an LDA for a specified connection established through the XA interface. For a description of the SQLLD2 call, see the Programmer’s Guide to the Oracle Call Interface. Note that OCOM, OCON, OCOF, ORLON, OLON, OLOG, and OLOGOF cannot be issued by an X/Open application.

Linking

To get XA functionality, you must link the XA library to your X/Open application object modules. For instructions, see your system-specific Oracle manuals.

33.6. Using Host Variables

In Section 33.4 you saw how you can execute SQL statements from an embedded SQL program. Some of those statements only used fixed values and d >host variables. In an embedded SQL program we cons >guests in the C program code which is the host language. Therefore the variables of the C program are called host variables.

33.6.1. Overview

Passing data between the C program and the SQL statements is particularly simple in embedded SQL. Instead of having the program paste the data into the statement, which entails various complications, such as properly quoting the value, you can simply write the name of a C variable into the SQL statement, prefixed by a colon. For example:

This statements refers to two C variables named v1 and v2 and also uses a regular SQL string literal, to illustrate that you are not restricted to use one kind of data or the other.

This style of inserting C variables in SQL statements works anywhere a value expression is expected in an SQL statement.

33.6.2. Declare Sections

To pass data from the program to the database, for example as parameters in a query, or to pass data from the database back to the program, the C variables that are intended to contain this data need to be declared in specially marked sections, so the embedded SQL preprocessor is made aware of them.

This section starts with:

Between those lines, there must be normal C variable declarations, such as:

As you can see, you can optionally assign an initial value to the variable. The variable’s scope is determined by the location of its declaring section within the program. You can also declare variables with the following syntax which implicitly creates a declare section:

You can have as many declare sections in a program as you like.

The declarations are also echoed to the output file as normal C variables, so there’s no need to declare them again. Variables that are not intended to be used in SQL commands can be declared normally outside these special sections.

The definition of a structure or union also must be listed ins >DECLARE section. Otherwise the preprocessor cannot handle these types since it does not know the definition.

33.6.3. Different types of host variables

As a host variable you can also use arrays, typedefs, structs and pointers. Moreover there are special types of host variables that exist only in ECPG.

A few examples on host variables:

One of the most common uses of an array declaration is probably the allocation of a char array as in:

Note that you have to take care of the length for yourself. If you use this host variable as the target variable of a query which returns a string with more than 49 characters, a buffer overflow occurs.

Use the typedef keyword to map new types to already existing types.

Note that you could also use:

This declaration does not need to be part of a declare section.

You can declare pointers to the most common types. Note however that you cannot use pointers as target variables of queries without auto-allocation. See Section 33.9 for more information on auto-allocation.

Special types of variables

ECPG contains some special types that help you to interact easily with data from the SQL server. For example it has implemented support for the varchar, numeric, date, timestamp, and interval types. Section 33.8 contains basic functions to deal with those types, such that you do not need to send a query to the SQL server just for adding an interval to a timestamp for example.

The special type VARCHAR is converted into a named struct for every variable. A declaration like:

is converted into:

This structure is suitable for interfacing with SQL datums of type varchar.

33.6.4. SELECT INTO and FETCH INTO

Now you should be able to pass data generated by your program into an SQL command. But how do you retrieve the results of a query? For that purpose, embedded SQL prov >SELECT and FETCH. These commands have a special INTO clause that specifies which host variables the retrieved values are to be stored in.

Here is an example:

So the INTO clause appears between the select list and the FROM clause. The number of elements in the select list and the list after INTO (also called the target list) must be equal.

Here is an example using the command FETCH:

Here the INTO clause appears after all the normal clauses.

33.6.5. Indicators

The examples above do not handle null values. In fact, the retrieval examples will raise an error if they fetch a null value from the database. To be able to pass null values to the database or retrieve null values from the database, you need to append a second host variable specification to each host variable that contains data. This second host variable is called the indicator and contains a flag that tells whether the datum is null, in which case the value of the real host variable is ignored. Here is an example that handles the retrieval of null values correctly:

The indicator variable val_ind will be zero if the value was not null, and it will be negative if the value was null.

The indicator has another function: if the indicator value is positive, it means that the value is not null, but it was truncated when it was stored in the host variable.

Понимание SQL (71 стр.)

* Для каждого иного символа в

, один и тот же символ устанавливается у соответствующей отметке в .

Если совпадение произошло,
— верен, если не был указан NOT. Фраза NOT LIKE ‘текст’ — эквивалентна NOT (A LIKE ‘текст’).

=IS NULL, если NULL значение представлено в этом столбце. Это сделает верным если не указан NULL. Фраза IS NOT NULL, имеет тот же результат что и NOT ( IS NULL ).

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

Это сравнение оценивается следующим образом:

* Если =ALL, и каждый член набора результатов делает это сравнение верным, — верен.

* Если =ANY, и имеется по крайней мере один член из набора результатов , который делает верным это сравнение, то является верным.

* Если набор результатов пуст, то верен, если =ALL, и неверен если иначе.

* Если =SOME, эффект — тот же что и для ANY.

* Если не верен и не неверен, он — неизвестен.

Если подзапрос выводит одну или более строк вывода, — верен; и неверен если иначе.

Этот раздел подробно описывает синтаксис различных команд SQL. Это даст вам возможность быстро отыскивать команду, находить ее синтаксис и краткое описание ее работы.

ИМЕЙТЕ ВВИДУ Команды которые начинаются словами — EXEC SQL, а также команды или предложения заканчивающиеся словом — могут использоваться только во вложенном SQL.

BEGIN DECLARE SECTION (НАЧАЛО РАЗДЕЛА ОБЪЯВЛЕНИЙ)

EXEC SQL BEGIN DECLARE SECTION

EXEC SQL END DECLARE SECTION

Эта команда создает раздел программы главного языка для обьявления в ней главных переменных, которые будут использоваться во вкладываемых операторах SQL. Переменная SQLCODE должна быть включена как одна из обьявляемых переменных главного языка.

CLOSE CURSOR (ЗАКРЫТЬ КУРСОР)

EXEC SQL CLOSE CURSOR ;

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

COMMIT (WORK) (ФИКСАЦИЯ (ТРАНЗАКЦИИ))

Эта команда оставляет неизменными все изменения сделанных в базе данных, до тех пор пока начавшаяся транзакция не закончится, и не начнется новая транзакция.

CREATE INDEX (*NONSTANDARD*) (СОЗДАТЬ ИНДЕКС) (НЕСТАНДАРТНО)

CREATE [UNIQUE] INDEX

Эта команда создает эффективный маршрут с быстрым доступом для поиска строк содержащих обозначенные столбцы. Если UNIQUE — указана, таблица не сможет содержать дубликатов(двойников) значений в этих столбцах.

CREATE SYNONYM (*NONSTANDARD*) (СОЗДАТЬ СИНОНИМ) (*НЕСТАНДАРТНО*)

CREATE IPUBLICl SYNONYM FOR

Эта команда создает альтернативное(синоним) имя для таблицы. Синоним принадлежит его создателю, а сама таблица, обычно другому пользователю. Используя синоним, его владелец может не ссылаться к таблице ее полным (включая имя владельца ) именем. Если PUBLIC — указан, синоним принадлежит каталогу SYSTEM и следовательно доступен всем пользователям.

CREATE TABLE (СОЗДАТЬ ТАБЛИЦУ)

Команда создает таблицу в базе данных. Эта таблица будет принадлежать ее создателю. Столбцы будут рассматриваться в поименном порядке. — определяет тип данных который будет содержать столбец. Стандарт описывается в Приложении B; все прочие используемые типы данных , обсуждались в Приложении C. Значение размера зависит от типа данных . и налагают ограничения на значения которые могут быть введены в столбцу. определяет значение(по умолчанию) которое будет вставлено автоматически, если никакого другого значения не указано для этой строки. (См. Главу 17 для подробностей о самой команде CREATE TABLE и Главы 18 И 19 для подробностей об ограничениях и о ).

CREATE VIEW (СОЗДАТЬ ПРОСМОТР)

[WITH CHECK OPTION];

Просмотр обрабатывается как любая таблица в командах SQL. Когда команда ссылается на имя таблицы

Name Code Description
CHAR 96
, запрос выполняется, и его вывод соответствует содержанию таблицы указнной в этой команде.

Некоторые просмотры могут модифицироваться, что означает, что команды модификации могут выполняться в этих просмотрах и передаваться в таблицу, на которую была ссылка в запросе . Если указано предложение WITH CHECK OPTION, эта модификация должны также удовлетворять условию предиката

DECLARE CURSOR (ОБЬЯВИТЬ КУРСОР)

EXEC SQL DECLARE CURSOR FOR

Эта команда связывает имя курсора , с запросом . Когда курсор открыт (см. OPEN CURSOR ), запрос выполняется, и его результат может быть выбран(командой FETCH) для вывода. Если курсор модифицируемый, таблица на которую ссылается запрос , может получить изменение содержания с помощью операции модификации в курсоре (См. Главу 25 о модифицируемых курсорах ).

DELETE (УДАЛИТЬ)

| WHERE CURRENT OF

, строки, которые удовлетворяют условию этого предиката

удаляются. Если предложение WHERE имеет аргумент CURRENT OF(ТЕКУЩИЙ) в имени курсора , строка из таблицы

на которую в данный момент имеется ссылка с помощью имени курсора будет удалена. Форма WHERE CURRENT может использоваться только во вложенном SQL, и только с модифицируемыми курсорами.

EXEC SQL (ВЫПОЛНИТЬ SQL)

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

FETCH (ВЫБОРКА)

FETCH принимает вывод из текущей строки запроса , вставляет ее в список главных переменных , и перемещает курсор на следующую строку. Список может включать переменную indicator в качестве целевой переменной (См. Главу 25. )

2
Precompiler Concepts

This chapter explains how embedded SQL programs do their work. Definitions of important words, explanations of basic concepts, and «rules
of the road» are presented.

Topics covered are:

Key Concepts of Embedded SQL Programming

This section lays the conceptual foundation on which later chapters build.

Steps in Developing an Embedded SQL Application

Precompiling results in a source file that can be compiled normally. Although precompiling adds a step to the traditional development process, that step is well worth taking because it lets you write very flexible applications.

Figure 2-1 walks you through the embedded SQL application development process:

Figure 2-1 Application Development Process


Embedded SQL Statements

The term embedded SQL refers to SQL statements placed within an application program. Because the application program houses the SQL statements, it is called a host program , and the language in which it is written is called the host language . For example, with Pro*COBOL you can embed SQL statements in a COBOL host program.

To manipulate and query Oracle data, you use the INSERT, UPDATE, DELETE, and SELECT statements. INSERT adds rows of data to database tables, UPDATE modifies rows, DELETE removes unwanted rows, and SELECT retrieves rows that meet your search criteria.

Only SQL statements—not SQL*Plus statements—are valid in an application program. (SQL*Plus has additional statements for setting environment parameters, editing, and report formatting.)

Executable versus Declarative Statements

Embedded SQL includes all the interactive SQL statements plus others that allow you to transfer data between Oracle and a host program. There are two types of embedded SQL statements: executable statements and directives .

Executable SQL statements generate calls to the database. They include almost all queries, DML (Data Manipulation Language), DDL (Data Definition Language), and DCL (Data Control Language) statements.

Directives , on the other hand, do not result in calls to SQLLIB and do not operate on Oracle data.

You use directives to declare Oracle objects, communications areas, and SQL variables. They can be placed wherever COBOL declarations can be placed.

Appendix F, «Embedded SQL Statements and Precompiler Directives» contains a presentation of the most important statements and directives.Table 2-1 groups some examples of embedded SQL statements (not a complete list):

Table 2-1 Embedded SQL Statements

STATEMENT

PURPOSE

ARRAYLEN*

To use host tables with PL/SQL

BEGIN DECLARE SECTION*

END DECLARE SECTION*

To declare host variables

DECLARE*

To name Oracle objects

INCLUDE*

To copy in files

To equivalence variables

WHENEVER*

To handle runtime errors

STATEMENT

PURPOSE

TRUNCATE

To define and control Oracle data

UPDATE

To query and manipulate Oracle data

SET TRANSACTION

To process transactions

PREPARE*

To use dynamic SQL

SET ROLE

To control sessions

Embedded SQL Syntax

In your application program, you can freely intermix SQL statements with host-language statements and use host-language variables in SQL statements. The only special requirement for building SQL statements into your host program is that you begin them with the words EXEC SQL and end them with the token END-EXEC. Pro*COBOL translates all executable EXEC SQL statements into calls to the runtime library SQLLIB.

Most embedded SQL statements differ from their interactive counterparts only through the addition of a new clause or the use of program variables. Compare the following interactive and embedded ROLLBACK statements:

A period or any other terminator can follow a SQL statement. Either of the following is allowed:

Static versus Dynamic SQL Statements

Most application programs are designed to process static SQL statements and fixed transactions. In this case, you know the makeup of each SQL statement and transaction before run time. That is, you know which SQL commands will be issued, which database tables might be changed, which columns will be updated, and so on. See Chapter 5, «Embedded SQL».

However, some applications are required to accept and process any valid SQL statement at run time. So, you might not know until then all the SQL commands, database tables, and columns involved.

Dynamic SQL is an advanced programming technique that lets your program accept or build SQL statements at run time and take explicit control over datatype conversion. See Chapter 9, «Oracle Dynamic SQL», Chapter 10, «ANSI Dynamic SQL», and Chapter 11, «Oracle Dynamic SQL: Method 4».

Embedded PL/SQL Blocks

Pro*COBOL treats a PL/SQL block like a single embedded SQL statement. So, you can place a PL/SQL block anywhere in an application program that you can place a SQL statement. To embed PL/SQL in your host program, you simply declare the variables to be shared with PL/SQL and bracket the PL/SQL block with the keywords EXEC SQL EXECUTE and END-EXEC.

From embedded PL/SQL blocks, you can manipulate Oracle data flexibly and safely because PL/SQL supports all SQL data manipulation and transaction processing commands. For more information about PL/SQL, see Chapter 6, «Embedded PL/SQL».

Host Variables and Indicator Variables

A host variable is a scalar or table variable or group item declared in the COBOL language and shared with Oracle, meaning that both your program and Oracle can reference its value. Host variables are the key to communication between Oracle and your program.

You use input host variables to pass data to the database. You use output host variables to pass data and status information from the database to your program.

Host variables can be used anywhere an expression can be used. But, in SQL statements, host variables must be prefixed with a colon, ‘:’, to set them apart from database schema names.

You can associate any host variable with an optional indicator variable. An indicator variable is an integer variable that indicates the value or condition of its host variable. A NULL is a missing, an unknown, or an inapplicable value. You use indicator variables to assign NULLs to input host variables and to detect NULLs in output variables or truncated values in output character host variables.

A host variable must not be


    prefixed with a colon in COBOL statements

used in data definition (DDL) statements such as ALTER and CREATE

In SQL statements, an indicator variable must be prefixed with a colon and appended to its associated host variable (to improve readability, you can precede the indicator variable with the optional keyword INDICATOR).

Every program variable used in a SQL statement must be declared according to the rules of the COBOL language. Normal rules of scope apply. COBOL variable names can be any length, but only the first 30 characters are significant for Pro*COBOL. Any valid COBOL identifier can be used as a host variable identifier, including those beginning with digits.

The external datatype of a host variable and the internal datatype of its source or target database column need not be the same, but they must be compatible. Table 4-9, «Conversions Between Internal and External Datatypes» shows the compatible datatypes between which Oracle8 i converts automatically when necessary.

Oracle Datatypes

Typically, a host program inputs data to the database, and the database outputs data to the program. Oracle inserts input data into database tables and selects output data into program host variables. To store a data item, Oracle must know its datatype , which specifies a storage format and valid range of values.

Oracle recognizes two kinds of datatypes: internal and external . Internal datatypes specify how Oracle stores data in database columns. Oracle also uses internal datatypes to represent database pseudo-columns, which return specific data items but are not actual columns in a table.

External datatypes specify how data is stored in host variables. When your host program inputs data to Oracle, if necessary, Oracle converts between the external datatype of the input host variable and the internal datatype of the database column. When Oracle outputs data to your host program, if necessary, Oracle converts between the internal datatype of the database column and the external datatype of the output host variable.

Note: You can override default datatype conversions by using dynamic SQL Method 4 or datatype equivalencing. For information about datatype equivalencing, see «Datatype Equivalencing» .

Tables

Pro*COBOL lets you define table host variables (called host tables ) and operate on them with a single SQL statement. Using the SELECT, FETCH, DELETE, INSERT, and UPDATE statements, you can query and manipulate large volumes of data with ease.

For a complete discussion of host tables, see Chapter 7, «Host Tables».

Errors and Warnings

When you execute an embedded SQL statement, it either succeeds or fails, and might result in an error or warning. You need a way to handle these results. Pro*COBOL provides these error handling mechanisms:


    SQLCODE status variable

SQLSTATE status variable

SQL Communications Area (SQLCA)

Oracle Communications Area (ORACA)

SQLCODE/SQLSTATE Status Variables

After executing a SQL statement, the Oracle Server returns a status code to a variable named SQLCODE or SQLSTATE. The status code indicates whether the SQL statement executed successfully or caused an error or warning condition.

SQLCA Status Variable

The SQLCA is a data structure that defines program variables used by Oracle to pass runtime status information to the program. With the SQLCA, you can take different actions based on feedback from Oracle about work just attempted. For example, you can check to see if a DELETE statement succeeded and if so, how many rows were deleted.

The SQLCA prov >i . After executing a SQL statement, Oracle8 i sets SQLCA variables to indicate the outcome, as illustrated in Figure 2-2.

Figure 2-2 Updating the SQLCA

You can check to see if an INSERT, UPDATE, or DELETE statement succeeded and if so, how many rows were affected. Or, if the statement failed, you can get more information about what happened.

When MODE=, you must declare the SQLCA by hard-coding it or by copying it into your program with the INCLUDE statement. The section «Using the SQL Communications Area» shows you how to declare and use the SQLCA.

WHENEVER Statement

With the WHENEVER statement, you can specify actions to be taken automatically when Oracle detects an error or warning condition. These actions include continuing with the next statement, calling a subprogram, branching to a labeled statement, performing a paragraph, or stopping.

ORACA

When more information is needed about runtime errors than the SQLCA provides, you can use the ORACA. The ORACA is a data structure that handles Oracle communication. It contains cursor statistics, information about the current SQL statement, option settings, and system statistics.

Precompiler Options and Error Handling

Oracle returns the success or failure of SQL statements in status variables, SQLSTATE and SQLCODE. With precompiler option MODE=ORACLE, you use SQLCODE, declared by including SQLCA. With MODE=ANSI, either SQLSTATE or SQLCODE must be declared, but SQLCA is not necessary.

Programming Guidelines

This section deals with embedded SQL syntax, coding conventions, and Pro*COBOL-specific features and restrictions.

Note: Topics are arranged alphabetically for quick reference.

Abbreviations

You can use the standard COBOL abbreviations, such as PIC for PICTURE IS and COMP for USAGE IS COMPUTATIONAL.

Case-Insensitivity

Pro*COBOL precompiler options and values as well as all EXEC SQL statements, inline commands, and COBOL statements are case-insensitive. The precompiler accepts both upper- and lower-case tokens.

COBOL Versions Supported

Pro*COBOL supports the standard implementation of COBOL for your operating system (usually COBOL-85 or COBOL-74). Some platforms may support both COBOL implementations. For more information, see your Oracle system-specific documentation.

Coding Areas

The precompiler option FORMAT, specifies the format of your source code. If you specify FORMAT=ANSI (the default), you are conforming as much as possible to the ANSI standard, in which columns 1 through 6 can contain an optional sequence number, and column 7 (indicator area) can indicate comments or continuation lines.

Division headers, section headers, paragraph names, FD and 01 statements begin in columns 8 through 11 (area A). Other statements, including EXEC SQL and EXEC ORACLE statements, must be placed in area B (columns 12 through 72). These guidelines for source code format can be overridden by your compiler’s rules.

If you specify FORMAT=TERMINAL, COBOL statements can begin in column 1 (the left-most column), or column one can be the indicator area. This is also subject to the rules of your compiler.

Consult your COBOL compiler documentation for your own platform to determine the actual acceptable formats for COBOL statements.

Note: In this manual, COBOL code examples use the FORMAT=TERMINAL setting. The online sample programs in the demo directory use FORMAT=ANSI.

Commas

In SQL, you must use commas to separate list items, as the following example shows:

In COBOL, you can use commas or blanks to separate list items. For example, the following two statements are equivalent:

Comments

You can place COBOL comment lines within SQL statements. COBOL comment lines start with an asterisk (*) in the indicator area.

You can also place ANSI SQL-style comments starting with «- — » within SQL statements at the end of a line (but not after the last line of the SQL statement).

COBOL comments continue for the rest of the line after these two characters: «*>».

You can place C-style comments (/* . */) in SQL statements.

The following example shows all four styles of comments:

You cannot nest comments or place them on the last line of a SQL statement after the terminator END-EXEC.

Continuation Lines

You can continue SQL statements from one line to the next, according to the rules of COBOL, as this example shows:

No continuation indicator is needed.

To continue a string literal from one line to the next, code the literal through column 72. On the next line, code a hyphen (-) in column 7, a quote in column 12 or beyond, and then the rest of the literal. An example follows:

Copy Statements

Copy statements are not supported by Pro*COBOL. Instead, use the INCLUDE precompiler statement which is documented on «Using the INCLUDE Statement» . Be careful when using INCLUDE and also using DECLARE_SECTION=YES. Group items should be either placed all inside or all outside of a Declare Section.

Decimal-Point is Comma

Pro*COBOL supports the DECIMAL-POINT IS COMMA clause in the ENVIRONMENT DIVISION. If the DECIMAL-POINT IS COMMA clause appears in the source file, then the comma will be allowed as the symbol beginning the decimal part of any numeric literals in the VALUE clauses.

For example, the following is allowed:

Delimiters

The LITDELIM option specifies the delimiters for COBOL string constants and literals. If you specify LITDELIM=APOST, the Pro*COBOL uses apostrophes when generating COBOL code. If you specify LITDELIM=QUOTE (default), quotation marks are used, as in

In SQL statements, you must use quotation marks to delimit identifiers containing special or lowercase characters, as in

However, you must use apostrophes to delimit string constants, as in

Regardless of which delimiter is used in the Pro*COBOL source file, Pro*COBOL generates the delimiter specified by the LITDELIM value.

Division Headers that are Optional

The following division headers are optional:

Note that the PROCEDURE DIVISION header is not optional. The following source can be precompiled:

Embedded SQL Syntax

To use a SQL statement in your Pro*COBOL program, precede the SQL statement with the EXEC SQL clause, and end the statement with the END-EXEC keyword. Embedded SQL syntax is described in the Oracle8 Server SQL Reference .

Figurative Constants

Figurative constants, such as HIGH-VALUE, ZERO, and SPACE, cannot be used in SQL statements. For example, the following is invalid :

Instead, use the following:

File Length

Pro*COBOL cannot process arbitrarily long source files. Some of the variables used internally limit the size of the generated file. There is no absolute limit to the number of lines allowed, but the following aspects of the source file are contributing factors to the file-size constraint:


    complexity of the embedded SQL statements (for example, the number of bind and define variables)

whether a database name is used (for example, connecting to a database with an AT clause)

number of embedded SQL statements

To prevent problems related to this limitation, use multiple program units to sufficiently reduce the size of the source files.

FILLER is Allowed

The word FILLER is allowed in host variable declarations. The word FILLER is used to specify an elementary item of a group that cannot be referred to explicitly. The following declaration is valid:

Host Variable Names

Any valid standard COBOL identifier can be used as a host variable. Variable names can be any length, but only the first 30 characters are significant. The maximum number of significant characters recognized by COBOL compilers is 30.

For SQL92 standards conformance, restrict the length of host variable names to 18 or fewer characters.

For a list of words that have restrictions on their use in applications, see Appendix C, «Reserved Words, Keywords, and Namespaces».

Hyphenated Names

You can use hyphenated host-variable names in static SQL statements but not in dynamic SQL. For example, the following usage is invalid :

Level Numbers

When declaring host variables, you can use level numbers 01 through 49, and 77. Pro*COBOL does not allow variables containing the VARYING clause, or pseudo-type variables (these datatypes are prefixed with «SQL- «) to be declared level 49 or 77.

MAXLITERAL Default

With the MAXLITERAL option, you can specify the maximum length of string literals generated by Pro*COBOL, so that compiler limits are not exceeded. For Pro*COBOL, the default value is 256, but you might have to specify a lower value.

Multi-Byte Datatypes

ANSI standard National Character Set datatypes are supported for handling multi-byte character data. The PIC N or PIC G clause, if supported by your compiler, defines variables that store fixed-length NCHAR strings. You can store variable-length, multi-byte National Character Set strings using COBOL group items consisting of a length field and a string field. See «VARCHAR Variables» .

The environmental variable NLS_NCHAR is available to specify a client-side National Character Set.

NULLs in SQL

In SQL, a NULL represents a missing, unknown, or inapplicable column value; it equates neither to zero nor to a blank. Use the NVL function to convert NULLs to non-NULL values, use the IS [NOT] NULL comparison operator to search for NULLs, and use indicator variables to insert and test for NULLs.

Paragraph and Section Names

You can associate standard COBOL paragraph and section names with SQL statements, as shown in the following example:

Also, you can reference paragraph and section names in a WHENEVER . DO or WHENEVER . GOTO statement, as the next example shows:

You must begin all paragraph names in area A.

REDEFINES Clause

You can use the COBOL REDEFINES clause to redefine group or elementary items. For example, the following declarations are valid:

Pro*COBOL issues no warning or error if a single INTO clause uses items from both a group item host variable and from its re-definition.

Relational Operators

COBOL relational operators differ from their SQL equivalents, as shown in Table 2-2. Furthermore, COBOL allows the use of words instead of symbols, whereas SQL does not.

Table 2-2 Relational Operators

Directives
Executable SQL

=, EQUAL TO

NOT=, NOT EQUAL TO

>, GREATER THAN

>=, GREATER THAN OR EQUAL TO

A COBOL sentence includes one or more COBOL and/or SQL statements and ends with a period. In conditional sentences, only the last statement must end with a period, as the following example shows.

SQL statements may be ended by a comma, a period, or another COBOL statement.

The Declare Section

Passing data between the database server and your application program requires host variables and error handling. This section shows you how to meet these requirements.

What is a Declare Section?

A Declare Section , begins with the statement:

and ends with the statement:

Between these two statements only the following are allowed:


    host-variable and indicator-variable declarations

non-host COBOL variables

EXEC SQL DECLARE statements

EXEC SQL INCLUDE statements

EXEC SQL VAR statements

EXEC ORACLE statements

An Example

In the following example, you declare four host variables for use later in your program.

Precompiler Option DECLARE_SECTION

The Declare Section is optional. For backward compatibility with releases prior to 8.0, for which it was required, Pro*COBOL provides a command-line precompiler option for explicit control over whether only declarations in the Declare Section are allowed as host variables. This option is

DECLARE_SECTION= (default is NO)

You must use the DECLARE_SECTION option on the command line or in a configuration file.

When the precompiler option DECLARE_SECTION is set to NO (the default), the Declare Section is optional. This optional behavior is a change from Pro*COBOL prior to release 8.0. If DECLARE_SECTION is YES, you must declare all program variables used in SQL statements inside the Declare Section.

If DECLARE_SECTION is set to NO, it is optional to use a Declare Section. Then declarations of host variables and indicator variables can be made either inside or outside a Declare Section. See «DECLARE_SECTION» for details of the option.

Multiple Declare Sections are allowed per precompiled unit. Furthermore, a host program can contain several independently precompiled units.

Using the INCLUDE Statement

The INCLUDE statement lets you copy files into your host program, as the following example shows:

You can INCLUDE any file. When you precompile your Pro*COBOL program, each EXEC SQL INCLUDE statement is replaced by a copy of the file named in the statement.

Filename Extensions

If your system uses file extensions but you do not specify one, Pro*COBOL assumes the default extension for source files (usually COB). For more information, see your Oracle system-specific documentation.

Search Paths

If your system uses directories, you can set a search path for included files using the INCLUDE option, as follows:

where path defaults to the current directory.

Pro*COBOL first searches the current directory, then the directory specified by the INCLUDE option, and finally the directory for standard INCLUDE files. You need not specify a path for standard files such as the SQLCA and ORACA. However, a path is required for nonstandard files unless they are stored in the current directory.

You can also specify multiple paths on the command line, as follows:

When multiple paths are specified, Pro*COBOL searches the current directory first, then the path1 directory, then the path2 directory, and so on. The directory containing standard INCLUDE files is searched last. The path syntax is system specific. For more information, see your Oracle system-specific documentation.

Note: Remember that Pro*COBOL searches for a file in the current directory first even if you specify a search path. If the file you want to INCLUDE is in another directory, make sure no file with the same name is in the current directory or any other directory that precedes it in the search path. If your operating system is case sensitive, be sure to specify the same upper/lowercase filename under which the file is stored.

Nested Programs

Nesting programs in COBOL means that you place one program inside another. The contained programs may reference some of the resources of the programs within which they are contained. The names within the higher-level program and the nested program can be the same, and describe different data items without conflict, because the names are known only within the programs. However, names described in the Configuration Section of the higher-level program can be referenced in the nested program.

Some compilers do not support the GLOBAL clause. Pro*COBOL supports nested programs by generating code that contains GLOBAL clauses. To avo >

The higher-level program can contain several nested programs. Likewise, nested programs can have programs nested within them. You must place the nested program directly before the END PROGRAM header of the program in which it is nested.

You can call a nested program only by a program in which it is either directly or indirectly nested. If you want a nested program to be called by any program, even one on a different branch of the nested tree structure, you code the COMMON clause in the PROGRAM-ID paragraph of the nested program. You can code COMMON only for nested programs:

You can code the GLOBAL phrase for File Definitions and level 01 data items (any subordinate items automatically become global). This allows them to be referenced in all subprograms directly or indirectly contained within them. You code GLOBAL on the higher-level program. If the nested program defines the same name as one declared GLOBAL in a higher-level program, COBOL uses the declaration within the nested program. If the data item contains a REDEFINES clause, GLOBAL must follow it.

Support for Nested Programs

Pro*COBOL allows nested programs with embedded SQL within a single source file. All 01 level items which are marked as global in a containing program and are valid host variables at the containing program level are usable as valid host variables in any programs directly or indirectly contained by the containing program. Consider the following example:

The main program declares the host variable REC1 as global and thus the nested program can use REC1 in the first select statement without having to declare it. Since VAR1 is declared as a global variable and also as a local variable in the nested program, the second select statement will use the VAR1 declared as S9(4), overriding the global declaration. In the third select statement, the global VAR1 of REC1 declared as PIC X(10) is used.

The previous paragraph describes the results when DECLARE_SECTION=NO is used. When DECLARE_SECTION=YES, Pro*COBOL will not recognize host variables unless they are declared ins >

Note: Recursive nested programs are not supported

Declaring the SQLCA

About declaring the SQLCA for nested programs, (see «SQLCA Status Variable» ), the included SQLCA definition provided will be declared as global, so the declaration of SQLCA is only required in the higher-level program. The SQLCA can change each time a new SQL statement is executed. The SQLCA provided can always be modified to remove the global specification if you want to declare additional SQLCA areas in the nested programs. The same will apply to SQLDA and ORACA.

Nested Program Example

See SAMPLE13.PCO in the demo directory.

Conditional Precompilations

Conditional precompilation includes (or excludes) sections of code in your host program based on certain conditions. For example, you might want to include one section of code when precompiling under UNIX and another section when precompiling under VMS. Conditional precompilation lets you write programs that can run in different environments.

Conditional sections of code are marked by statements that define the environment and actions to take. You can code host-language statements as well as EXEC SQL statements in these sections. The following statements let you exercise conditional control over precompilation:

A conditional statement must be terminated with END-EXEC.

Note: The conditional compilation feature of your compiler may not be supported by Pro*COBOL.

An Example

In the following example, the SELECT statement is precompiled only when the symbol SITE2 is defined:

Blocks of conditions can be nested as shown in the following example:

You can «Comment out» host-language or embedded SQL code by placing it between IFDEF and ENDIF and not defining the symbol.

Defining Symbols

You can define a symbol in two ways. Either include the statement

in your host program or define the symbol on the command line using the syntax

where symbol is not case-sensitive.

Some port-specific symbols are predefined for you when Pro*COBOL is installed on your system. For example, predefined operating system symbols include CMS, MVS, UNIX, and VMS.

Separate Precompilations

You can precompile several COBOL program modules separately, then link them into one executable program. This supports modular programming, which is required when the functional components of a program are written and debugged by different programmers. The individual program modules need not be written in the same language.

Guidelines

The following guidelines will help you avoid some common problems.

Referencing Cursors

Cursor names are SQL identifiers, whose scope is the precompilation unit. Hence, cursor operations cannot span precompilation units (files). That is, you cannot declare a cursor in one file and open or fetch from it in another file. So, when doing a separate precompilation, make sure all definitions and references to a given cursor are in one file.

Specifying MAXOPENCURSORS

When you precompile the program module that connects to Oracle, specify a value for MAXOPENCURSORS that is high enough for any of the program modules. If you use it for another program module, MAXOPENCURSORS is ignored. Only the value in effect for the connect is used at run time.

Using a Single SQLCA

If you want to use just one SQLCA, you must declare it globally in SQLCA.COB by changing the line

Using a Single DATE_FORMAT

You must use the same format string for DATE in each program module.

Restrictions

All references to an explicit cursor must be in the same program file. You cannot perform operations on a cursor that was DECLAREd in a different module. See Chapter 4 for more information about cursors.

Also, any program file that contains SQL statements must have a SQLCA that is in the scope of the local SQL statements.

Compiling and Linking

To get an executable program, you must compile the source file(s) produced by Pro*COBOL, then link the resulting object module with any modules needed from SQLLIB and system-specific Oracle libraries.

The linker resolves symbolic references in the object modules. If these references conflict, the link fails. This can happen when you try to link third party software into a precompiled program. Not all third-party software is compatible with Oracle, so you might have problems. Check with Oracle Customer Support to see if the software is supported.

Compiling and linking are system-dependent. For example, on some systems, you must turn off compiler optimization when compiling a host language program. For instructions, see your system-specific Oracle manual.

Sample Tables

Most of the complete program examples in this guide use two sample database tables: DEPT and EMP. If they do not exist in your demo directory, create them before running the sample programs. Their definitions follow:

Sample Data

Respectively, the DEPT and EMP tables contain the following rows of data:

Sample Programs: SAMPLE1.PCO

A good way to get acquainted with embedded SQL is to look at a program example. This program is SAMPLE1.PCO in the demo directory.

The program logs on to the database, prompts the user for an employee number, queries the database table EMP for the employee’s name, salary, and commission. The selected results are stored in host variables EMP-NAME, SALARY, and COMMISSION. The program uses the host indicator variable, COMM-IND to detect NULL values in column COMMISSION. See «Indicator Variables» .

The paragraph DISPLAY-INFO then displays the result.

The COBOL variables USERNAME, PASSWD, and EMP-NUMBER are declared using the VARYING clause, which allows you to use a variable-length string external Oracle datatype called VARCHAR. This datatype is explained in «VARCHAR Variables» .

The SQLCA Communications Area is included to handle errors. If an error occurs, paragraph SQL-ERROR is performed. See «Using the SQL Communications Area» .

The BEGIN DECLARE SECTION and END DECLARE SECTION statements used are optional, unless you set the precompiler option DECLARE_SECTION to YES, or option MODE to ANSI. See «MODE» .

The WHENEVER statement is used to handle errors. For more details, see «WHENEVER Directive» .

The program ends when the user enters a zero employee number.

Используя Pro * C, как использовать структуру C++ с конструктором, скопируйте конструктор в EXEC SQL BEGIN DECLARE SECTION

Я использую Pro * C версии 12.2.0.1.0. Чтобы использовать массивы хостов в операторе SQL INSERT, я использую массив структур, как показано ниже:

Моя команда pro * c build выглядит так:

Но когда я компилирую, используя Pro * C Compiler, используя code=cpp , как в proc code=cpp . , , Я получаю ошибку, как указано ниже:

Мне нужно использовать структуру C++ с конструктором и конструктором копирования, чтобы позаботиться об инициализации, но чтобы компилятор Pro * C принял это? Следующее объявление разрешено, но мне нужно использовать конструкторы для инициализации:

Согласно документации, опция CODE=CPP указывает Pro C генерировать C++, а не C. Она ничего не говорит о коде, который вы ему предоставляете.

Вы можете изменить режим «parse» на PARTIAL чтобы разрешить синтаксис C++ в предоставленном вами коде.

Для генерации кода, совместимого с C++, опция PARSE должна быть NONE или PARTIAL. Если PARSE=FULL , синтаксический анализатор C запускается, и он не понимает конструкции C++ в вашем коде, такие как классы.

Как ни странно, PARSE=PARTIAL считается значением по умолчанию, когда вы CODE=CPP , но, похоже, это не работает, как показывает ошибка:

Неустранимая ошибка при выполнении предварительной обработки C

… Что должно быть невозможным, поскольку полная предварительная обработка C должна происходить только в режиме PARSE=FULL . Также смутно возможно, что парсер Pro C++ не работает так, что он принимает функции-члены только в классе, определенном с помощью ключевого слова class . Я говорю это только потому, что распространенное заблуждение состоит в том, что классы, определенные с помощью struct ключевого слова, не могут содержать такие вещи — вы можете попробовать настроить свой код, чтобы увидеть, не ошиблись ли авторы парсера.

Иллюстрированный самоучитель по SQL для начинающих

Использование SQL в приложениях

Объявление базовых переменных

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

А конец этого сегмента отмечается с помощью такого выражения:

Перед каждым оператором SQL должна стоять директива SQL EXEC. Конец сегмента SQL может быть отмечен директивой завершения. В языке COBOL такой директивой является ‘»END-EXEC», а в языке FORTRAN – это конец строки, а в языках Ada, С, Pascal и PL/1 – точка с запятой.

Преобразование типов данных

В зависимости от типов данных, поддерживаемых базовым языком и языком SQL, вам, воз-рсно, для преобразования некоторых из этих типов данных придется использовать оператор CAST. Можно использовать базовые переменные, которые были объявлены с помощью DECLARE SECTION. А когда в операторах SQL применяются имена этих переменных, то не надо забывать следующее: перед этими именами необходимо ставить двоеточие (:). Это как раз и делается в следующем примере с таблицей FOODS (продукты питания) со столбцами FOODNAME (название продукта), CALORIES (калории), PROTEIN (белки), FAT (жиры), CARBOHYDRATE (углеводы):

Модульный язык

Использовать SQL вместе с процедурным программным языком можно и по-другому – с помощью модульного языка. Благодаря ему вы сможете разместить все операторы SQL в отдельном модуле SQL.

Помни:
Модуль SQL– это список команд SQL. Каждая из этих команд вызывается процедурой SQL, и перед ней стоят имя процедуры, имена и типы ее параметров
.

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

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

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

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

Приложение D

СИНТАКСИС И СПРАВКА ПО КОМАНДАМ

В этом приложении содержатся сокращённые описания различных команд SQL. Цель состоит в том, чтобы дать вам быструю и точную справку и определение SQL.

Первый раздел этого приложения определяет элементы, используемые для создания команд SQL; второй — подробности синтаксиса и предложения с кратким описанием самих команд.

Вот стандартные условные обозначения (они называются BNF-условиями):

  • Ключевые слова набираются в верхнем регистре.
  • SQL и другие специальные условия заключаются в угловые скобки и набираются курсивом.( )
  • Необязательные части команд находятся в квадратных скобках ( [ и ] ).
  • Многоточие ( . ) указывает на то, что предшествующая часть команды может повторяться любое число раз.
  • Вертикальная полоса ( | ) означает: то, что ей предшествует, может быть заменено на то, что следует за ней.
  • Фигурные Скобки ( < и >) указывают: всё, что внутри них, должно быть расценено как целое, для оценки других символов (например, вертикальных полос или эллипсов).
  • Двойное двоеточие и знак равенства (:: = ) означают: то, что следует за ними, является определением того, что им предшествует.

    Кроме того, мы будем использовать следующую последовательность ( . ) чтобы указывать, что предшествующее этому может повторяться любое число раз, с индивидуальными событиями, отделяемыми запятыми. Атрибуты, которые не являются частью официального стандарта, будут отмечены в описании как (*нестандартные*).

    ОБРАТИТЕ ВНИМАНИЕ: Терминология которую мы используем здесь — не является официальной терминологией ANSI. Официальная терминология может вас сильно запутать, поэтому мы несколько ее упростили.
    По этой причине мы иногда используем условия, отличающиеся от ANSI, или используем те же самые условия, но несколько по-иному. Например, наше определение

    ФУНКЦИОНАЛЬНЫЕ ЭЛЕМЕНТЫ

    ПРЕДИКАТЫ

    Здесь определён список различных типов предиката

    Эти таблицы читаются способом, наподобие таблицы умножения: вы объединяете верные, неверные, или неизвестные значения из строк с их столбцами, чтобы на перекрестье получить результат. В таблице AND, например, третий столбец (Неизвестно) и первая строка (Тrue) на пересечении в верхнем правом углу дают результат — неизвестно, другими словами: Верно AND Неизвестно = неизвестно. Порядок вычислений определяется круглыми скобками. Они не представляются каждый раз. NOT оценивается первым, далее AND и OR. Различные типы предикатов

    рассматриваются отдельно в следующем разделе.

    Если либо = NULL, либо = неизвестно;
    другими словами, это true, если сравнение true, или false, если сравнение false.

    имеет стандартные математические значения для числовых значений; для других типов значений эти значения определяются конкретной реализацией.

    Оба должны иметь сравнимые типы данных. Если подзапрос используется, он должен содержать одно выражение в предложении SELECT, чьё значение будет заменять второе выражение в предикате сравнения каждый раз, когда действительно выполняется.

    [NOT] BETWEEN
    AND

    — A BETWEEN B AND C имеет такое же значение, что и

    — ( A>= B AND , для которого A NOT BETWEEN B AND C, имеет такое же значение, что и NOT (BETWEEN B AND C).
    может быть выведено с помощью нестандартного запроса (*nonstandard*).

    Список значений будет состоять из одного или более значений в круглых скобках с разделением запятыми, которые имеют сравнимый с тип данных. Если используется подзапрос , он должен содержать только одно выражение в предложении SELECT (возможно и больше, но это уже будет вне стандарта ANSI).
    Подзапрос фактически выполняется отдельно для каждой строки-кандидата основного запроса, и значения, которые он выведет, будут составлять список значений для этой строки. В любом случае предикат будет верен, если выражение представленное в списке значений , если не указан NOT.
    Фраза A NOT IN (B, C) является эквивалентом фразы NOT (A IN (B, C)).

    это любое *нестандартное* выражение алфавитно-цифрового типа.
    может быть, в соответствии со стандартом, только определенным столбцом . Образец

    состоит из строки, которая будет проверена на совпадение с . Символ окончания это одиночный алфавитно-цифровой символ. Совпадение произойдет, если верны следующие условия:

    Для каждого символа подчёркивания в образце

    , который не предшествует символу окончания , имеется один соответствующий ему символ .
    Для каждого

    , который не предшествует , имеются нуль или более соответствующих символов в .
    Для каждого в

    , который не предшествует другому , нет никакого соответствующего символа в .
    Для каждого иного символа в

    , один и тот же символ устанавливается у соответствующей отметке в .

    Если совпадение произошло,
    верен, если не был указан NOT. Фраза NOT LIKE ‘текст’ — эквивалентна NOT (A LIKE ‘текст’).

    = IS NULL, если NULL значение представлено в этом столбце. Это сделает верным, если не указан NULL. Фраза IS NOT NULL, имеет тот же результат что и NOT ( IS NULL).

    Предложение SELECT подзапроса должно содержать одно, и только одно, выражение значения . Все значения, выведенные подзапросом , составляют набор результатов . сравнивается, используя оператор связи , с каждым членом набора результатов . Это сравнение оценивается следующим образом:

  • Если = ALL и каждый член набора результатов делает это сравнение верным, верен.
  • Если = ANY и имеется по крайней мере один член из набора результатов , который делает верным это сравнение, то является верным.
  • Если набор результатов пуст, то верен, если = ALL , и неверен а ином случае.
  • Если = SOME, эффект — тот же, что и для ANY.
  • Если неверен и не неверен, он неизвестен.

    Если подзапрос выводит одну или более строк вывода, верен; и неверен в ином случае.

    SQL КОМАНДЫ

    Этот раздел подробно описывает синтаксис различных команд SQL. Это даст вам возможность быстро отыскивать команду, находить синтаксис и краткое описание её работы.

    ИМЕЙТЕ ВВИДУ: команды, которые начинаются словами — EXEC SQL, а также команды или предложения, заканчивающиеся словом, могут использоваться только во вложенном SQL.

    BEGIN DECLARE SECTION (НАЧАТЬ РАЗДЕЛ ОБЪЯВЛЕНИЙ)

    EXEC SQL BEGIN DECLARE SECTION EXEC SQL END DECLARE SECTION

    Эта команда создает главный раздел программы для объявления в ней главных переменных, которые будут использоваться во вкладываемых операторах SQL. Переменная SQLCODE должна быть включена как одна из объявляемых переменных главного языка.

    CLOSE CURSOR (ЗАКРЫТЬ КУРСОР)

    EXEC SQL CLOSE CURSOR ;

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

    COMMIT (WORK) (ПОДТВЕРДИТЬ (ТРАНЗАКЦИИ))

    Эта команда оставляет неизменными все изменения, сделанных в базе данных, до тех пор, пока начавшаяся транзакция не закончится и не начнется новая транзакция.

    CREATE INDEX (СОЗДАТЬ ИНДЕКС)

    Эта команда создает эффективный маршрут с быстрым доступом для поиска строк, содержащих указанные столбцы. Если UNIQUE указана, таблица не сможет содержать дубликаты (двойники) значений в этих столбцах.

    CREATE SYNONYM (*NONSTANDARD*)
    (СОЗДАТЬ СИНОНИМ) (*НЕСТАНДАРТНЫЙ*)

    CREATE IPUBLICl SYNONYM FOR
    .

  • SQL Operators COBOL Operators
    ;

    Эта команда создает альтернативное (синоним) имя таблицы. Синоним принадлежит его создателю, а сама таблица — обычно другому пользователю. Используя синоним, его владелец может не ссылаться на таблицу её полным (с включением имени владельца) именем. Если PUBLIC указан, синоним принадлежит каталогу SYSTEM и, следовательно, доступен всем пользователям.

    CREATE TABLE (СОЗДАТЬ ТАБЛИЦУ)

    Команда создает таблицу в базе данных. Эта таблица будет принадлежать её создателю. Столбцы будут рассматриваться в поимённом порядке.
    определяет тип данных, которые столбец будет содержать. Стандарт описывается в Приложении B; все прочие используемые типы данных обсуждались в Приложении C. Значение размера зависит от типа данных .
    и налагают ограничения на значения, которые могут быть введены в столбце.
    определяет значение (по умолчанию), которое будет вставлено автоматически, если никакого другого значения не указано для этой строки. (См. в Главе 17 подробности о самой команде CREATE TABLE и в Главах 18 И 19 — подробности об ограничениях и о ).

    CREATE VIEW (СОЗДАТЬ ПРОСМОТР)

    CREATE VIEW

    AS
    [WITH CHECK OPTION];

    Просмотр обрабатывается как любая таблица в командах SQL. Когда команда ссылается на имя таблицы

    , запрос выполняется, и его вывод соответствует содержанию таблицы, указанной в этой команде.
    Некоторые просмотры могут модифицироваться, что означает, что команды модификации могут выполняться в этих просмотрах и передаваться в таблицу, на которую была ссылка в запросе . Если указано предложение WITH CHECK OPTION, эта модификация должны также удовлетворять условию предиката
    DECLARE CURSOR (ОБЪЯВИТЬ КУРСОР)

    EXEC SQL DECLARE CURSOR FOR

    Эта команда связывает имя курсора с запросом . Когда курсор открыт (см. OPEN CURSOR ), запрос выполняется, и его результат может быть выбран (командой FETCH) для вывода. Если курсор — модифицируемый, таблица, на которую ссылается запрос , может получить изменение содержания с помощью операции модификации в курсоре (См. в Главе 25 о модифицируемых курсорах).

    DELETE (УДАЛИТЬ)

    ]; >
    | WHERE CURRENT OF

    Если предложение WHERE отсутствует, ВСЕ строки таблицы удаляются. Если предложение WHERE использует предикат

    , строки, которые удовлетворяют условию этого предиката

    , удаляются. Если предложение WHERE имеет аргумент CURRENT OF (ТЕКУЩИЙ) в имени курсора , строка из таблицы

    , на которую в данный момент имеется ссылка с помощью имени курсора , будет удалена. Форма WHERE CURRENT может использоваться только во вложенном SQL и только с модифицируемыми курсорами.
    EXEC SQL (ВЫПОЛНИТЬ SQL)

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

    FETCH (ВЫБОРКА/ИЗВЛЕЧЕНИЕ)

    EXEC SQL FETCH
    INTO

    FETCH принимает вывод из текущей строки запроса , вставляет её в список главных переменных , и перемещает курсор на следующую строку. Список может включать переменную indicator в качестве целевой переменной (См. Главу 25).

    GRANT (ПЕРЕДАТЬ ПРАВА)

    GRANT ALL [PRIVILEGES]
    | | INSERT
    | DELETE
    | UPDATE [( )]
    | REFERENCES [( )l > . , . .
    ON

    . , . .
    TO PUBLIC | . , . .
    [WITH GRANT OPTION];

    Аргумент ALL (ВСЕ), с или без PRIVILEGES (ПРИВИЛЕГИИ), включает каждую привилегию в список привилегий. PUBLIC (ОБЩИЙ) включает всех существующих пользователей и всех созданных в будущем. Эта команда даёт возможность передать права для выполнения действий в таблице с указанным именем. REFERENCES позволяет дать права на использование столбцов в списке столбцов как родительский ключ для внешнего ключа. Другие привилегии состоят из права выполнять команды, для которых привилегии указаны их именами в таблице. UPDATE подобен REFERENCES и может накладывать ограничения на определенные столбцы. GRANT OPTION даёт возможность передавать эти привилегии другим пользователям.

    CONNECT дает возможность передавать право на регистрацию и некоторые другие ограниченные права.
    RESOURCE дает пользователю право создавать таблицы.
    DBA дает возможность передавать почти все права.
    IDENTIFIED BY используется вместе с CONNECT для создания или изменения пароля пользователя.

    INSERT (ВСТАВИТЬ)

    INSERT INTO

    ( )
    VALUES ( ) I ;

    INSERT создает одну или больше новых строк в таблице

    . Если используется предложение VALUES, значения строк вставляются в таблицу
    . Если запрос указан, каждая строка вывода будет вставлена в таблицу
    . Если список столбцов отсутствует, все столбцы таблицы
    OPEN CURSOR (ОТКРЫТЬ КУРСОР)

    EXEC SQL OPEN CURSOR

    OPEN CURSOR выполняет запрос, связанный с курсором . Вывод может теперь извлекать по одной строке для каждой команды FETCH.

    REVOKE (*NONSTANDARD*)
    (ОТМЕНИТЬ ПОЛНОМОЧИЯ) (НЕСТАНДАРТНАЯ)

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

    ROLLBACK (WORK)
    (ОТКАТ) (ТРАНЗАКЦИИ)

    Команда отменяет все изменения в базе данных, сделанные в течение текущей транзакции. Она, кроме того, заканчивается текущую и начинает новую транзакцию.

    SELECT (ВЫБОР)

    ]
    [GROUP BY . , . .]
    [HAVING

    Это предложение организует запрос и выводит значения из базы данных (см. Главы 3 — 14 ).

    Применяются следующие правила:

    применяется к каждой строке, произведённой предложением GROUP BY, и те строки, которые сделают этот предикат верным, будут выведены.
    Если ORDER BY используется, вывод имеет определенную последовательность. Каждый идентификатор столбца ссылается на указанное в предложении SELECT. Если это является указанным столбцом , может быть таким же, как . Иначе может быть положительным целым числом, указывающим место, где находится в последовательности предложения SELECT. Вывод будет сформирован так, чтобы помещать значения, содержащиеся в , в порядке возрастания, если DESC не указан. Имя идентификатора столбца , стоящее первым в предложении ORDER BY, будет предшествовать позже стоящим именам в определении последовательности вывода.

    Предложение SELECT оценивает каждую строку-кандидат таблицы, в которой строки показаны независимо.

    Строка-кандидат определяется следующим образом:

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

    Каждая строка-кандидат производит значения, которые делают предикат

    в предложении WHERE верным, неверным, или неизвестным. Если GROUP BY не используется, каждое применяется, в свою очередь, для каждой строки-кандидата, чьё значение делает предикат верным, и результатом этой операции является вывод.
    Если GROUP BY используется, строки-кандидаты комбинируются, используя агрегатные функции. Если никакого предиката

    не установлено, каждое выражение применяется к каждой строке-кандидату или к каждой группе. Если указан DISTINCT, дубликаты (двойники) строк будут удалены из вывода.

    UNION (ОБЪЕДИНЕНИЕ)

    Вывод двух или более запросов будет объединён. Каждый запрос должен содержать один и тот же номер в предложении SELECT и в таком порядке, что 1.. n каждого совместим по типу данных и размеру с 1.. n всех других.

    UPDATE (МОДИФИКАЦИЯ)

    UPDATE изменяет значения в каждом столбце на соответствующее значение . Если предложение WHERE использует предикат

    , то только строки таблиц, чьи текущие значения делают этот предикат

    верным, могут быть изменены. Если WHERE использует предложение CURRENT OF, то значения в строке таблицы

    , находящиеся в курсоре , меняются. WHERE CURRENT OF пригодно для использования только во вложенном SQL, и только с модифицируемыми курсорами. При отсутствии предложения WHERE, все строки меняются.

    ВНЕДРЕНИЕ ОПЕРАТОРОВ SQL

    В большинстве продуктов SQL операторы языка SQL могут выполняться как непосредственно (т.е. интерактивно, с подключенного терминала), так и в виде части прикладной программы (т.е. операторы SQL могут быть внедренными, а значит, могут смешиваться с операторами базового языка этой программы). Приложения, использующие внедренные операторы SQL, могут быть написаны на многих базовых языках; стандарт SQL включает поддержку для Ada, С, COBOL, Fortran, Java, M (прежде известного как MUMPS), Pascal и PL/I. Рассмотрим особенности технологии внедрения операторов SQL более подробно.

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

    Прежде чем начать обсуждение конкретных внедряемых операторов SQL, необходимо обсудить некоторые детали. Большинство из них иллюстрируется фрагментом программы, представленным на рис. 4.3. (Для закрепления наших представлений будем считать, что базовым языком является PL/I. Большинство приводимых примеров транслируется на другие базовые языки лишь с незначительными изменениями.)

    Рассмотрим этот фрагмент программы.

    1. Внедренные операторы SQL предваряются инструкцией EXEC SQL, так что их лег ко отличить от других операторов базового языка, и заканчиваются специальным завершающим символом (для языка PL/I таковым является точка с запятой «; «).

    2. Выполняемый оператор SQL (далее и до конца этого раздела уточняющее слово вне дренный обычно не будет применяться) может быть в программе везде, где могут находиться выполняемые операторы базового языка. Обратите внимание на уточ няющее слово выполняемый: в отличие от интерактивного режима использования языка SQL, режим внедрения операторов SQL подразумевает включение в про грамму отдельных операторов SQL, которые являются чисто декларативными, а не выполняемыми. Например, оператор DECLARE CURSOR — это не выполняемый оператор (подробности приводятся в разделе «Операции, в которых используются курсоры»); таковыми не являются и операторы BEGIN и END DECLARE SECTION (см. п. 5 этого списка), а также оператор WHENEVER (СМ. П. 9).

    EXEC SQL BEGIN DECLARE SECTION ; DCL SQLSTATE CHAR(5) ; DCL P# CHAR(6) ; DCL WEIGHT FIXED DECIMAL(5,1) ;

    EXEC SQL END DECLARE SECTION ;

    P# = ‘ P2 ‘ ; /* Рассматривается в качестве примера */ EXEC SQL SELECT P.WEIGHT

    INTO :WEIGHT FROM P

    WHERE P.P# = P# ( :P# ) ; IF SQLSTATE = ‘00000’ THEN …

    ; /* WEIGHT значение, полученное путем выборки */ ELSE … ; /* Возникло некоторое исключение */

    Рис. 4.3. Фрагмент программы на языке PL/I с внедренными операторами языка SQL

    3. Операторы SQL могут включать ссылки на базовые переменные (т.е. переменные базового языка). Подобные ссылки должны иметь префикс в виде двоеточия, позволяющий отличить их от имен столбцов таблиц SQL. Базовые переменные могут применяться во внедренных операторах SQL везде, где в интерактивном языке SQL могут использоваться литералы. Они могут также находиться в предложении INTO операторов SELECT (см. п. 4) и FETCH (подробности — в разделе «Операции, в которых используются курсоры»), определяющем результирующие переменные для размещения результатов выборки данных.

    4. Обратите внимание на конструкцию INTO оператора SELECT, представленного на рис. 4.3. Назначение этой конструкции (как только что отмечалось) — указать ре зультирующие (целевые) переменные, в которых будут возвращены выбранные зна чения. Каждая /-я целевая переменная, указанная в предложении INTO, соответству ет /-му извлекаемому значению, указанному в списке выборки предложения SELECT.

    5. Все базовые переменные, на которые ссылаются внедренные операторы SQL, долж ны быть определены в разделе объявлений внедренного языка SQL, который ограни чивается операторами BEGIN DECLARE SECTION И END DECLARE SECTION

    (в PL/I для этого используется операторDCL).

    6. Каждая программа, содержащая внедренные операторы SQL, должна включать ба зовую переменную с именем SQLSTATE. После выполнения любого присутствую щего в программе оператора SQL в эту переменную возвращается код состояния. В частности, код состояния 00000 означает, что оператор был выполнен успешно, а код состояния 02000 — что оператор был выполнен, но никаких удовлетворяю щих запросу данных найдено не было (другие значения указаны в [4.23]). Таким образом, выполнение в программе каждого оператора SQL должно завершаться проверкой значения переменной SQLSTATE и, если это значение будет отличаться от ожидаемого, должны предприниматься соответствующие действия. На практи ке, однако, такая проверка обычно выполняется неявно (см. п. 9).

    7. Каждая переменная базового языка должна иметь тип данных, соответствующий значениям, для хранения которых эта переменная используется. В частности, базовая переменная, используемая в качестве целевой (например, для хранения результатов операции SELECT), должна иметь тип данных, совместимый с типом выражения, значение которого присваивается этой целевой базовой переменной. Аналогично, если базовая переменная служит источником (например, для опера ции INSERT), она должна иметь тип данных, совместимый с типом SQL того столбца, которому присваивается значение из этого источника. Но эта тема явля ется гораздо более сложной по сравнению со сведениями, приведенными в данной главе, поэтому она здесь не рассматривается (по крайней мере, достаточно под робно), а ее дальнейшее обсуждение будет продолжено в главе 5, раздел 5.7.

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

    9. Как уже упоминалось, выполнение каждого оператора SQL, в принципе, должно сопровождаться проверкой значения, возвращаемого в переменной SQLSTATE. Для упрощения этого процесса предназначен оператор WHENEVER, который имеет следующий синтаксис.

    EXEC SQL WHENEVER >’,

    ■ NOT FOUND показывает, что не найдены данные, соответствующие оператору;

    значение SQLSTATE = 02ххх;

    ■ SQLWARNING означает, что возникла незначительная ошибка; значение

    ■ SQLEXCEPTION означает, что возникла серьезная ошибка (исключительная си туация); значения SQLSTATE приведены в [4.23].

    Каждый оператор WHENEVER (для определенного условия), встреченный компилятором при последовательном просмотре текста программы, отменяет предыдущий (для этого условия).

    Используя терминологию главы 2, отметим, что внедрение операторов SQL устанавливает слабую связь между средой SQL и базовым языком.

    Итак, для предварительного обсуждения этого достаточно. В остальной части этого раздела главным образом рассматриваются операторы манипулирования данными. Как уже отмечалось, большинство из них можно использовать практически в неизменном виде (т.е. лишь с незначительными изменениями в синтаксисе). Однако операции выборки требуют отдельного описания. Проблема состоит в том, что такие операторы в общем случае выбирают не одну, а множество строк, в то время как процедурные базовые языки обычно не приспособлены для выборки больше одной строки за одно обращение. Следовательно, необходимо создать своего рода «мост» между предусмотренными в языке SQL средствами выборки, позволяющими получать одновременно множество строк, и применяемыми в базовом языке средствами обработки, допускающими одновременное использование только одной строки. В качестве подобного «моста» используются курсоры. Курсор представляет собой своего рода логический указатель, который может использоваться в приложении для перемещения по набору строк, указывая поочередно на каждую из них и таким образом обеспечивая возможность адресации этих строк — по одной за один раз. Однако временно отложим подробное обсуждение курсоров (до подраздела «Операции, в которых используются курсоры») и рассмотрим сначала такие операторы, для которых курсоры не требуются.

    Операции, в которых не используются курсоры

    Ниже перечислены операторы манипулирования данными, для которых не требуется использование курсоров.

    ■ Однострочный оператор SELECT.

    ■ UPDATE (кроме формы CURRENT — см. следующий подраздел).

    ■ DELETE (также кроме формы CURRENT — см. следующий подраздел).

    Рассмотрим примеры каждого из этих операторов.

    Однострочный оператор SELECT. Получить статус и название города для поставщика, номер которого задан в базовой переменной GlVENS#.

    EXEC SQL SELECT STATUS, CITY INTO :RANK, :TOWN FROM S WHERE S# = S# ( :GIVENS# )

    Термин однострочный оператор SELECT используется для обозначения выражения SELECT, значением которого будет таблица, содержащая не больше одной строки. В данном примере, если в таблице S существует одна и только одна строка, отвечающая заданному условию в конструкции WHERE, значения столбцов STATUS и CITY из этой строки в соответствии с запросом будут присвоены базовым переменным RANK и CITY, а переменной SQLSTATE будет присвоено значение 00000. Если в таблице S нет ни одной строки, отвечающей заданному условию WHERE, переменной SQLSTATE будет присвоено значение 02000. Если же таких строк окажется больше одной, будет зафиксирована ошибка и переменная SQLSTATE будет содержать ее код.

    Оператор INSERT. Вставить в таблицу Р сведения о новой детали (номер детали, ее название и вес задаются содержимым базовых переменных Р#, PNAME, PWT, соответственно; цвет детали и город неизвестны).

    EXEC SQL INSERT

    INTO P ( P#, PNAME, WEIGHT ) VALUES ( :P#, :PNAME, :PWT )

    Столбцам COLOR и CITY вновь добавляемой строки таблицы будут присвоены соответствующие значения, применяемые по умолчанию. Подробнее об этом речь пойдет в разделе 6.6 главы 6. Следует отметить, что по причинам, анализ которых выходит за рамки данной книги, применяемое по умолчанию значение для столбца, который имеет некоторый тип, определяемый пользователем, обязательно должно быть неопределенным (NULL). (Подробное обсуждение темы, касающейся неопределенных значений, откладывается до главы 19; однако нам неизбежно придется время от времени возвращаться к этому вопросу.)

    Оператор DELETE. Удалить сведения обо всех поставках для поставщиков из города, название которого помещено в базовую переменную CITY.

    EXEC SQL DELETE FROM SP

    ( SELECT CITY FROM S

    И снова, если нет строк, удовлетворяющих условию WHERE, переменной SQLSTATE присваивается значение 02000. Также обратите внимание на вложенный подзапрос (на этот раз в предложении WHERE).

    Оператор UPDATE. Увеличить статус всех поставщиков из Лондона на значение,

    помещенное в базовую переменную RAISE.

    EXEC SQL UPDATE S

    SET STATUS = STATUS +

    :RAISE WHERE CITY = ‘London1

    Если в таблице поставщиков не будет найдено строк, удовлетворяющих условию

    WHERE, система присвоит переменной SQLSTATE значение 02000.

    Операции, в которых используются курсоры

    Теперь перейдем к вопросу о выборках на уровне множеств, т.е. о выборках не одной строки, как это было в случае однострочного оператора SELECT, а множества с произвольным количеством строк. Как указывалось ранее, в этой ситуации потребуется поочередный доступ к строкам выбранного множества, а механизмом такого доступа будет курсор. На рис. 4.4 этот процесс схематически проиллюстрирован на примере выборки информации о поставщиках (столбцы s#, SNAME и STATUS) для всех поставщиков из города, название которого задается в базовой переменной У.

    EXEC SQL DECLARE X CURSOR FOR /* Определить курсор */ SELECT S.S#, S.SNAME, S.STATUS FROM S

    WHERE S.CITY = :Y ORDER BY Si ASC ;

    EXEC SQL OPEN X ; /* Выполнить запрос */ DO ;

    EXEC SQL FETCH X INTO :S#, :SNAME, :STATUS ;

    /* Получить данные о

    EXEC SQL CLOSE X ; /* Перевести курсор X в

    Рис. 4.4. Выборка нескольких строк

    Пояснение. Оператор DECLARE X CURSOR. . . определяет курсор х, связанный с табличным выражением (т.е. выражением, которое возвращает таблицу). Табличное выражение определяется оператором SELECT, который является частью всего выражения

    DECLARE, но не вычисляется в этом месте программы, поскольку оператор DECLARE CURSOR— чисто декларативный. Табличное выражение вычисляется только при открытии курсора (оператор OPEN X). Далее для выборки строк из результирующего множества, по одной за один раз, используется оператор FETCH X INTO. . ., присваивающий извлеченные значения базовым переменным в соответствии со спецификациями в конструкции INTO. (Для простоты базовым переменным присвоены имена, совпадающие с именами соответствующих столбцов таблицы базы данных. Обратите внимание, что в операторе SELECT при определении курсора не задается собственная конструкция INTO.) Поскольку в результирующем наборе потенциально присутствует большое количество строк, оператор FETCH обычно вызывается в цикле. Цикл будет повторяться до тех пор, пока не закончатся строки в результирующем наборе. После выхода из цикла курсор х закрывается (оператор CLOSE X).

    А теперь рассмотрим курсоры и операции с ними более подробно. Курсор определяется с помощью оператора DECLARE CURSOR, который имеет следующий общий вид.

    EXEC SQL DECLARE CURSOR FOR [ ] ;

    Для краткости несколько необязательных спецификаций в этом определении не указаны. Здесь параметр — это имя определяемого курсора. Необязательный параметр определения сортировки результата выборки имеет следующий формат.

    Здесь параметр разделенный запятыми список элементов , по которым должно быть выполнено упорядочение извлекаемых строк. Список должен содержать не меньше одного элемента , а в каждом элементе списка должно содержаться имя столбца (заметьте, неуточненное)4, после которого может следовать необязательное служебное слово ASC (по возрастанию) или DESC (по убыванию). При отсутствии служебного слова по умолчанию принимается порядок по возрастанию (ASC). Если конструкция ORDER BY не определена, то принцип упорядочения определяется системой. (Фактически, последнее замечание остается в силе, если даже определена конструкция ORDER BY, по крайней мере, когда речь идет о строках с одним и тем же значением для указанного списка .)

    Примечание. Дадим определение удобному термину разделенный запятыми список элементов (commalist). Пусть обозначает произвольную синтаксическую категорию (т.е. то, что находится слева от некоторого правила вывода в нотации BNF). Тогда выражение (или ) обозначает последовательность от нуля и больше элементов , в которой каждая пара элементов разделена

    4 Фактически, имя столбца может быть уточнено, если заданное табличное выражение

    соответствует довольно сложному набору правил. Эти правила были впервые введены в стандарте SQL: 1999, в котором также регламентированы правила, согласно которым элемент может иногда определять либо вычислительное выражение, например, ORDER BY A+B, либо имя столбца, который входит в состав таблицы результата, например, SELECT CITY FROM S ORDER BY STATUS. Изложение подробных сведений об этих правилах выходит за рамки настоящей книги.

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

    Как утверждалось ранее, оператор DECLARE CURSOR — декларативный, а не выполняемый. Он предназначен для объявления курсора с определенным именем, для которого предусмотрено табличное выражение и с которым постоянно связан тип упорядочения. Табличное выражение может включать ссылки на базовые переменные. Программа может содержать любое количество операторов DECLARE CURSOR, каждый из которых должен быть, конечно, предназначен для определения разных курсоров.

    Для работы с курсорами существует три выполняемых оператора: OPEN, FETCH И

    ■ Оператор OPEN имеет следующий формат.

    Он предназначен для открытия или активизации указанного курсора (который в данный момент не должен быть открыт). В результате его выполнения вычисляется связанное с этим курсором табличное выражение (причем для всех базовых переменных, упоминаемых в этом выражении, используются текущие значения). В результате идентифицируется определенное множество строк, которое становится текущим активным набором для данного курсора. Курсор также устанавливает исходную позицию в этом активном наборе, а именно — позицию перед его первой строкой. Следует отметить, что активные наборы всегда рассматриваются как упорядоченные (см. приведенное выше описание конструкции ORDER BY), а значит, и понятие позиции имеет для них смысл5.

    ■ Оператор FETCH имеет следующий формат.

    Здесь параметр —разделенный запятыми список ссылок на базовые переменные. Этот оператор служит для перемещения позиции указанного курсора (который должен быть уже открыт) к следующей строке в его активном наборе с последующим присваиванием значений столбцов этой строки базовым переменным, указанным в предложении INTO. Если после очередного вызова оператора FETCH на выполнение следующая строка отсутствует, то выборка данных не производится и переменной SQLSTATE присваивается значение 02 000.

    ■ Оператор CLOSE имеет следующий формат.

    5 Сами по себе множества, конечно, не являются упорядоченными (глава 6), так что «активный набор» — это на самом деле не множество как таковое. Его лучше представлять в виде упорядоченного списка или массива (строк).

    Он служит для закрытия (деактивизации) указанного курсора (который должен быть в данный момент открытым). После его выполнения с курсором уже не будет связан активный набор. Однако в дальнейшем курсор вновь может быть открыт; при этом он снова получит активный набор — возможно, уже не такой, как раньше (в частности, если значения указанных в объявлении курсора базовых переменных к текущему моменту были изменены). Следует отметить, что изменение этих переменных при открытом курсоре не оказывает влияния на его активный набор.

    Есть еще два оператора, в которых могут использоваться ссылки на курсоры, — это варианты операторов UPDATE и DELETE С конструкцией CURRENT. ЕСЛИ курсор (скажем, х) в данный момент позиционирован на определенную строку, то можно обновить или удалить эту «текущую строку курсора х», т.е. строку, на которую в данный момент позиционирован курсор х, например, как показано ниже.

    EXEC SQL UPDATE S

    SET STATUS = STATUS +

    :RAISE WHERE CURRENT OF X

    Выражения CURRENT операторов DELETE и UPDATE будут недопустимыми, если табличное выражение в объявлении курсора определено с участием необновляемого представления, созданного с помощью оператора CREATE VIEW (подробности приведены в главе 10, раздел 10.6).

    Динамический язык SQL и интерфейс SQL/CLI

    В предыдущем разделе по умолчанию предполагалось, что данная конкретная программа (включая операторы SQL и все операторы базового языка) может быть полностью откомпилирована «заблаговременно» (т.е. до наступления этапа прогона) в том виде, в каком она реализуется на данный момент. Однако применительно к некоторым приложениям соблюдение такого условия нельзя гарантировать. Например, рассмотрим оперативное приложение. (Напомним, что, как отмечалось в главе 1, оперативными называются приложения, которые предоставляют пользователю доступ к базе данных с некоторого интерактивного терминала или подобного ему устройства.) Как правило, в этом приложении должны выполняться примерно такие действия, как показано ниже.

    1. Принять с терминала команду пользователя.

    2. Проанализировать поступившую команду.

    3. Сгенерировать соответствующие операторы SQL для обращения к базе данных.

    4. Возвратить сообщение и (или) полученные результаты на терминал.

    Если набор команд пользователя, который программа может принять с терминала в шаге 1, достаточно мал (как, например, в случае обработки предварительных заказов мест на авиалиниях), то набор всех возможных выполняемых операторов SQL также будет невелик и его можно будет непосредственно внедрить в программу. В этом случае действия на втором и третьем этапах будут состоять в логической проверке введенной команды с последующим переходом к той части программы, которая выполняет заранее предопределенные операторы SQL. С другой стороны, если набор вводимых команд достаточно разнообразен, было бы непрактично заранее предопределять и внедрять в программу все

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

    Динамический язык SQL

    Средства динамического языка SQL — это часть средств поддержки внедрения языка SQL. Они состоят из множества динамических операторов (компиляция самих этих операторов осуществляется заблаговременно), назначение которых состоит именно в том, чтобы обеспечивать поддержку трансляции и выполнения обычных операторов SQL, создаваемых на этапе прогона программы. Таким образом, существуют два основных динамических оператора SQL — PREPARE (Подготовить — по сути, компилировать) и EXECUTE (Выполнить). Их использование проиллюстрировано на следующем (нереальном по своей простоте, но достаточно точном) примере на языке PL/I.

    Илон Маск рекомендует:  Что такое код dotnet_load
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL