Вы на НеОфициальном сайте факультета ЭиП

На нашем портале ежедневно выкладываются материалы способные помочь студентам. Курсовые, шпаргалки, ответы и еще куча всего что может понадобиться в учебе!
Главная Контакты Карта сайта
 
Где мы?

Реклама


Лекции по SQL. Часть 5.

Просмотров: 1569 Автор: admin

Лекции по SQL

<!--[if gte mso 9]> <!--[if gte mso 10]> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Обычная таблица"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} 1.1.1.1. SQLDescribeCol

 

Возвращает описание столбца. Прототип:

RETCODE SQLDescribeCol(

    HSTMT hstmt, // идентификатор оператора

    UWORD icol,  // номер столбца (от 1)

    UCHAR FAR *szColName, // куда поместить имя поля

    SWORD cbColNameMax, // длина буфера для имени

    SWORD FAR *pcbColName, // число байт в имени

    SWORD FAR *pfSqlType, // SQL-тип данных столбца

    UDWORD FAR *pcbColDef, // точность (?)

    SWORD FAR *pibScale, // размер поля

    SWORD FAR *pfNullable // допускаются ли NULL-значения

                          // SQL_NO_NULLS - нет

                          // SQL_NULLABLE - да

                          // SQL_NULLABLE_UNKNOWN - неизвестно

);

Дополнительная информация о столбце может быть  извлечена с помощью фун­кции SQLColAttributes.

 

1.1.1.2. SQLColAttributes

RETCODE SQLColAttributes (

    HSTMT hstmt, // идентификатор оператора

    UWORD icol, // номер столбца  ( начиная с 1)

    UWORD fDescType,  // что вы хотите узнать

    PTR  rgbDesc,  // указатель на возвращаемое значение

     SWORD cbDescMax,  // максимальная допустимая длина

                                             // возвращаемогозначения

     SWORD FAR * pcbDesc,  // действительная длина

                                                   // возвращаемого значения

     SDWORD FAR *pfDesc  // указатель на возвращаемое целое значение

                                                  // ( для таких запросов, как

                                                  // SQL_COLUMN_LENGTH

);

Входной параметр fDescType может принимать значения:

SQL_COLUMN_AUTO_INCREMENT

SQL_COLUMN_CASE_SENSITIVE

SQL_COLUMN_COUNT

SQL_COLUMN_DISPLAY_SIZE           Максимальное число символов,

                                                                     необходимое для отображения

                                                                     значения столбца

SQL_COLUMN_LABEL

SQL_COLUMN_LENGTH                       В pfDesc - длина  данных в байтах,

                                                                      которую получит SQLFetch или

                                                                      SQLGetData при условии, что для

                                                                      С-типа указано SQL_C_DEFAULT

SQL_COLUMN_MONEY

SQL_COLUMN_NAME

SQL_COLUMN_NULLABLE

SQL_NO_NULLS

SQL_COLUMN_OWNER_NAME

SQL_COLUMN_PRECISION                    Точность в pfDesc

SQL_COLUMN_QUALIFIER_NAME

SQL_COLUMN_SCALE

SQL_COLUMN_SEARCHABLE

SQL_COLUMN_TABLE_NAME

SQL_COLUMN_TYPE

SQL_COLUMN_UNSIGNED

SQL_COLUMN_UPDATABLE


1.1.2.    Выборка результатов запроса.

 

Результат работы  SQL-оператора  -  это либо множество строк, либо число строк,  на ко­то­рое воздействовал оператор, либо и то и другое. SELECT  возвращает  результи­ру­ющее  мно­жество,  а UPDATE, INSERT, DELETE - только число строк.  Например,  число строк  для оператора DELETE  -  это число удаленных им строк.  Чтобы получитьего, следует вызвать функцию SQLRowCount, описанную ниже.

Результирующее множество  создается одним набором функций, а вы­би­ра­ется другим.  После создания результирующего множества, оно еще рас­по­ла­га­ет­ся  на  сервере и должно быть извлечено прикладной программой клиента.

В отличие от VIEW или таблицы, перемещение по множеству является  од­но­направ­лен­ным.(МК - не во всех системах).  С результирующим множеством  свя­зан  "курсор",  отмеча­ющий  положение  текущей строки результата.  Понятие кур­сора аналогично, например, по­ня­тию рабочей области  CLIPPER.  (?) Курсор авто­матически создается для любого резуль­ти­рующего множества.

Непосредственно после создания,курсор устанавливается перед  пер­вой стро­кой множества.  Для перемещения курсора и извлечения данных исполь­зу­ют­ся фун­кции SQLFetch и SQLExtendedFetch.

SQLFetch каждый раз продвигает курсор на одну строку. SQLExtendedFetch имеет воз­мож­ность перемещать  курсор  по другому правилу.

В ODBC существует две функции базового уровня для выборки результатов: SQLBindCol  и SQLFetch.  SQLBindCol определяет область хранения данных множества,  а SQLFetch осуществляет выборку  данных.

Функция  SQLGetData может быть использована для выборки данных из столб­цов для которых область хранения не была подготовлена с помощью  SQLBindCol.

Алгоритм извлечения данных следующий.  SQLBindCol может  быть вызвана в любой момент времени для активного оператора.

    1) Вызывается SQLBindCol для каждого извлекаемого столбца.

    2) Для каждой извлекаемой строки вызывается SQLFetch.

1.1.2.1. SQLBindCol.

 

    Обращение к SQLBindCol имеет вид:

    RETCODE SQLBindCol(

       HSTMT hstmt, // идентификатор оператора

       UWORD icol,  // номер столбца. Нумерация от 1. Столбец 0-

                    // ROWID

       SWORD fCtype, // C-тип данных столбца.

       PTR   rgbValue, // Указатель области хранения данных

                       // Если указатель 0, то столбец

                       // "отвязывается"

       SDWORD cbValueMax, // сколько байт может принять буфер поля

       SDWORD FAR * pcbValue // Число на самом деле принятых байт

    )

 

Как только столбец связан,  он остается связанным до тех пор, пока не  бу­дет  вызвана  функция SQLFreeStmt с опциями SQL_UNBIND или SQL_DROP.

1.1.2.2.SQLFetch

 

Как только все  требуемые  столбцы  связаны,  можно  вызывать SQLFetch для выборки данных.

RETCODE SQLFetch(HSTMT hstmt);

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

RETCODE==SQL_NO_DATA_FOUND.

1.1.2.3.SQLGetData

 

Для выборки данных из несвязанных столбцов,  прикладная программамо­жет ис­поль­зовать SQLGetData. SQLGetData должен вызыватьсядля каждой стро­ки, в которой данные из­вле­каются.

 

RETCODE SQLGetData(

    HSTMT hstmt, // идентификатор оператора

    UWORD icol,  // номер столбца результата

    SWORD fCtype, // С-тип столбца

    PTR rgbValue, // куда девать выбранное значение

    SDWORD cbValueMax, // длина буфера

    SDWORD FAR *pcbValue // фактическая длина данных

);

Функция SQLGetData полезна в тех случаях, когда Вы не намерены извлекать дан­ные из каждой строки. Особенно это касается полейтипа MEMO.

 

1.1.2.4.Блочные курсоры

 

Блочные курсоры позволяют извлекать блок строк за раз. Этот блокназы­вается rowset или строковым множеством. Размер строкового множествауста­нав­ливается функцией SQLSetStmtOption  со значением fOption= SQL_ROWSET_SIZE и опцией vparam. Как только раз­мер строкового множества  ус­та­новлен, Вы связываете массив буферов хранения  извле­ка­емых значений с по­­­мощ­ью SQLBindCol. Предварительно нужно выделить память для хра­нения чис­­­ла байт, которые были возвращены для каждого значения данных. Наконец, мож­­­но вызвать  SQLBindCol, задавая адрес массива в rgbValue, размер одного эле­­­мента массива в cbValueMax и адрес массива числа байт в pcbValue. Теперь каж­­­дый вызов функции SQLExtendedFetch  будет возвращать заданное число строк из результирующего множества. Выборка множества строк может снизить се­те­вой трафик за счет снижения числа взаимо­дей­ствий между клиентом и сер­ве­­ром.  Возможно связывание также в массив структур дан­ных.

 

1.1.2.5. Перемещаемые курсоры

 

Курсор, обеспечиваемый SQLFetch способен перемещаться только вперед на одну стро­ку. Функция SQLExtendedFetch обеспечивает произвольное пере­ме­ще­ние курсора. Для того, чтобы использовать перемещаемые курсоры следует уста­новить тип курсора с помощью SQLSetStmtOption при fOption=

SQL_CURSOR_TYPE. Тип курсора по умолчанию - SQL_CURSOR_FORWARD_ONLY.

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

Статические курсоры (SQL_CURSOR_STATIC) полностью нечувствительны к изме­не­ни­ям в таб­ли­цах, на основе которых получено результирующее мно­жес­тво. Это означает, что после по­лу­чения резуль­ти­ру­ющего множества, оно будет оставаться неизменным до своего за­крытия.

Динамическиекурсоры  (SQL_CURSOR_DINAMIC) являются полностью чув­стви­тель­ны­ми к основным измене­ни­ям. К сожалению, динамические курсоры поддерживаются не­мно­гими драйверами.

Курсоры, управляемые ключами (SQL_CURSOR_KEYSET_DRIVEN) занимают проме­жу­точное положение. Их результирующее множество отражает об­­нов­ленные и удаленные стро­ки, но не новые. (DBF-драйвер отказался от SQL_CURSOR_DINAMIC и установил SQL_CURSOR_KEYSET_DRIVEN).

Для блочных курсоров допустим любой тип перемещения. Единицей пере­мещения яв­ля­ется блок.

К сожалению, SQLExtendedFetch является функцией второго уровня и не все драйверы ее поддерживают, а если поддерживают, то, может быть, не все спо­собы перемещения кур­со­ра. Это можно выяснить запросив SQLGetFunctions с fFunction=SQL_API_SQLEXTENDED­FETCH, а затем SQLGetInfo c fInfoType=SQL_FETCH_DIRECTION.

Связывание можно выполнить по столбцам или по строкам.

 

1.1.2.6.SQLExtendedFetch

 

Функция SQLExtendedFetch способна использовать перемещаемые иблочные курсоры. Курсоры могут быть блочные, перемещаемые и блочные иперемещаемые одновременно. Для каждого связанного столбца возвращается  мас­сив значений из множества строк.  Уста­новив соответствующий тип  пере­мещения Вы можете пере­мещаться по результирующему множествув про­из­воль­ном направлении. Обращение имеет вид:


RETCODE   SQLExtendedFetch (

      HSTMT hstmt,  // идентификатор оператора

      UWORD fFetchType,  // тип выборки

      SDWORD irow,  // число строк выборки

      UDWORD  FAR *pcrow,  // число реально извлеченных строк

      UWORD FAR *rgfRowStatus  // массив значений состояния

);

Параметр fFetchType может принимать значения:


SQL_FETCH_NEXT - извлекает следующее строковое множество

SQL_FETCH_FIRST -                  первое

SQL_FETCH_LAST -                   последнее

SQL_FETCH_PRIOR  -                предыдущее

SQL_FETCH_ABSOLUTE - извлекает строковое множество, начиная с N строки в результи­ру­ющем множестве, где N определяется irow.      

SQL_FETCH_RELATIVE - извлекает строковое множество, начиная с N строки по отно­ше­нию к  текущей позиции курсора, где N определяется параметром irow

SQL_FETCH_BOOKMARK - ?

 

В rgfRowStatus SQLExtendedFetch возвращает любые изменения статуса каж­­дой стро­ки с момента выполнения SQL-оператора. Строки могут быть не из­ме­­нены (SQL_ROW_SUCCESS), изменены (SQL_ROW_UPDATED), удалены (SQL_ROW_DELETED), добавлены (SQL_ROW_ADDED) или недоступны для выборки из-за ошибки (SQL_ROW_ERROR). Если число извлеченных строк мен­ь­ше, чем заказывали, то незаполненные структуры из массива получают ста­тус SQL_ROW_NOROW.


Связывание по столбцам

 

Чтобы назначить связывание по столбцам, программа должна вызвать SQLSetStmtOption и установить SQL_BIND_BY_COLUMN для fOption= SQL_BIND_TYPE(это умолчание).

Затем:

1) Далее, программа размещает для каждого свя­зываемого столбца массив буфе­ров для хранения данных, содержащий столь­ко элементов, сколько строк в мно­жестве плюс один дополнительный элемент для случая, когда программа будет выполнять поиск ключа или добавлять новые записи. Размер каждого буфера - это максимальный размер С - данных, которые могут быть приняты из столбца.

2) Размещает массив типа SDWORD для числа байт принимаемых из столбца для каждой строки результирующего множества.

3) Вызывает SQLBindCol, для которого rgbValue - адрес массива буферов, cbValueMax - размер одного буфера, pcbValue - адрес массива длин принимаемых данных.

 

Пример связывания по столбцам приведен ниже.

 

#define ROWS 100

#define NAME_LEN 30

#define BDAY_LEN 11

 

UCHAR     szName[ROWS][NAME_LEN], szBirthday[ROWS][BDAY_LEN];

SWORD     sAge[ROWS];

SDWORD    cbName[ROWS], cbAge[ROWS], cbBirthday[ROWS];

 

UDWORD    crow, irow;

UWORD     rgfRowStatus[ROWS];

 

SQLSetStmtOption(hstmt, SQL_CONCURRENCY, SQL_CONCUR_READ_ONLY);

SQLSetStmtOption(hstmt, SQL_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);

SQLSetStmtOption(hstmt, SQL_ROWSET_SIZE, ROWS);

retcode = SQLExecDirect(hstmt, "SELECT NAME, AGE, BIRTHDAY FROM EMPLOYEE ORDER BY 3, 2, 1", SQL_NTS);

 

if (retcode == SQL_SUCCESS) {

            SQLBindCol(hstmt, 1, SQL_C_CHAR, szName, NAME_LEN, cbName);

            SQLBindCol(hstmt, 2, SQL_C_SSHORT, sAge, 0, cbAge);

            SQLBindCol(hstmt, 3, SQL_C_CHAR, szBirthday, BDAY_LEN, cbBirthday);

 

            /* Fetch the rowset data and print each row. */

            /* On an error, display a message and exit.  */

 

            while (TRUE) {

                        retcode = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &crow, rgfRowStatus);

                        if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {

 

show_error();

                        }

                        if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){

                                   for (irow = 0; irow < crow; irow++) {

                                               if (rgfRowStatus[irow] != SQL_ROW_DELETED && rgfRowStatus[irow] != SQL_ROW_ERROR)

                                                           fprintf(out, "%-*s  %-2d  %*s", NAME_LEN-1, szName[irow], sAge[irow], BDAY_LEN-1, szBirthday[irow]);

                                   }

                        } else {

                                   break;

                        }

            }

}

 

Связывание по строкам


Для построчного связывания результирующего множества программа должна:

1) Объявить структуру, которая будет содержать одну строку результирующего множества и ассоциированную длину данных. Для каждого извлекаемого поля структура содержит одно поле для данных и одно SDWORD поле для возвра­ща­емой длины данных.. Длина извлекаемого поля - это максимальная длина данных которая может быть получена для значения столбца.

2) Вызывает SQLSetStmtOption с fOption=SQL_BIND_TYPE и vParam равным раз­ме­ру структуры.

3) Размещает массив таких структур. Массив имеет размерность результиру­ю­ще­го множества плюс один элемент для операций поиска и вставки.

4) Вызывает SQLBindCol для каждого связываемого столбца. Аргумент rgbValue - это адрес поля в первой структуре массива. CbValueMax - размер поля в принимающей структуре. pcbValue - адрес поля структуры в которую принима­ет­ся  действительная длина данных из столбца. Если длина данных неизвестна, то SQLExtendedFetch поместит  в pcbValue значение SQL_NO_TOTAL. Если значение поля не определено, то SQL_NULL_DATA.

 

Ниже приведен пример программы с использованием SQLExtendedFetch, использую­щий строковое связывание.

#define ROWS 100

#define NAME_LEN 30

#define BDAY_LEN 11

 

typedef struct {

            UCHAR     szName[NAME_LEN];

            SDWORD    cbName;

            SWORD     sAge;

            SDWORD    cbAge;

            UCHAR     szBirthday[BDAY_LEN];

            SDWORD    cbBirthday;

            }           EmpTable;

 

EmpTable rget[ROWS];

UDWORD   crow, irow;

UWORD    rgfRowStatus[ROWS];

 

SQLSetStmtOption(hstmt, SQL_BIND_TYPE, sizeof(EmpTable));

SQLSetStmtOption(hstmt, SQL_CONCURRENCY, SQL_CONCUR_READ_ONLY);

SQLSetStmtOption(hstmt, SQL_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);

 

SQLSetStmtOption(hstmt, SQL_ROWSET_SIZE, ROWS);

retcode = SQLExecDirect(hstmt, "SELECT NAME, AGE, BIRTHDAY FROM EMPLOYEE ORDER BY 3, 2, 1", SQL_NTS);

 

if (retcode == SQL_SUCCESS) {

            SQLBindCol(hstmt, 1, SQL_C_CHAR, rget[0].szName, NAME_LEN, &rget[0].cbName);

            SQLBindCol(hstmt, 2, SQL_C_SSHORT, &rget[0].sAge, 0, &rget[0].cbAge);

            SQLBindCol(hstmt, 3, SQL_C_CHAR, rget[0].szBirthday, BDAY_LEN, &rget[0].cbBirthday);

            /* Извлечь данные множества и напечатать все строки  */

 

/* При обнаружении ошибки показать сообщение и выйти .  */

 

            while (TRUE) {

                        retcode = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &crow, rgfRowStatus);

                        if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {

                                   show_error();

                        }

                        if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){

                                   for (irow = 0; irow < crow; irow++) {

                                               if (rgfRowStatus[irow] != SQL_ROW_DELETED && rgfRowStatus[irow] != SQL_ROW_ERROR)

                                                          fprintf(out, "%-*s  %-2d  %*s", NAME_LEN-1, rget[irow].szName, rget[irow].sAge, BDAY_LEN-1, rget[irow].szBirthday);

 

}

                        } else {

                                   break;

                        }

            }

}



Популярные новости

Статистика сайта



Rambler's Top100



 
Copyright © НеОфициальный сайт факультета ЭиП