Что такое код mssql_fetch_row


Содержание

mssql_fetch_row

mssql_fetch_row — получает ряд как перечислимый массив.

Описание

array mssql_fetch_row (int result)

Возвращает массив, соответствующий извлечённому ряду, или FALSE, если рядов больше нет.

mssql_fetch_row() извлекает один ряд данных из результата, ассоциированного со специфицированным результирующим идентификатором. Ряд возвращается как массив. Каждый результирующий столбец хранится как смещение массива, начиная со смещения 0.

Последующий вызов mssql_fetch_rows() извлечёт следующий ряд результирующего набора или возвратит FALSE, если рядов больше нет.

Linux.yaroslavl.ru

Учебник РНР
Назад Вперёд

mssql_fetch_row — получает ряд как перечислимый массив.

Описание

array mssql_fetch_row (int result)

Возвращает массив, соответствующий извлечённому ряду, или FALSE , если рядов больше нет.

mssql_fetch_row() извлекает один ряд данных из результата, ассоциированного со специфицированным результирующим идентификатором. Ряд возвращается как массив. Каждый результирующий столбец хранится как смещение массива, начиная со смещения 0.

Последующий вызов mssql_fetch_rows() извлечёт следующий ряд результирующего набора или возвратит FALSE , если рядов больше нет.

mssql_fetch_row

(PHP 4, PHP 5, PECL odbtp >= 1.1.1)

mssql_fetch_row — Get row as enumerated array

Описание

mssql_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to mssql_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

Список параметров

The result resource that is being evaluated. This result comes from a call to mssql_query() .

Возвращаемые значения

Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.

Примеры

Пример #1 mssql_fetch_row() example

// Connect to MSSQL and select the database
$link = mssql_connect ( ‘MANGO\SQLEXPRESS’ , ‘sa’ , ‘phpfi’ );
mssql_select_db ( ‘php’ , $link );

// Query to execute
$query = mssql_query ( ‘SELECT [ , $link );

// Did the query fail?
if (! $query ) <
die( ‘MSSQL error: ‘ . mssql_get_last_message ());
>

// Fetch the row
$row = mssql_fetch_row ( $query );

// Print the ‘quote’
echo ‘Quote #’ . $row [ 0 ] . ‘: «‘ . $row [ 1 ] . ‘»‘ ;
?>

Результатом выполнения данного примера будет что-то подобное:

Примечания

Замечание: Эта функция устанавливает NULL-поля в значение NULL PHP.

Смотрите также

  • mssql_fetch_array() — Fetch a result row as an associative array, a numeric array, or both
  • mssql_fetch_object() — Fetch row as object
  • mssql_data_seek() — Moves internal row pointer
  • mssql_result() — Get result data
НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/

[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

Что такое код mssql_fetch_row

ПРИМЕНЯЕТСЯ К: SQL Server (начиная с 2008) База данных SQL Azure Хранилище данных SQL Azure Parallel Data Warehouse

Возвращает состояние последней инструкции FETCH, вызванной в любом курсоре, открытом в данном соединении.

целое число

Возвращаемое значение Description
Инструкция FETCH была выполнена успешно.
-1 Выполнение инструкции FETCH завершилось неудачно или строка оказалась вне пределов результирующего набора.
-2 Выбранная строка отсутствует.
-9 Курсор не выполняет операцию выборки.

Поскольку @@FETCH_STATUS является глобальной для всех курсоров в соединении, используйте@FETCH_STATUS тщательно. После выполнения инструкции FETCH, проверка, @@FETCH_STATUS прежде, чем любая другая инструкция FETCH выполняется в отношении другого курсора. Значение @@FETCH_STATUS до любой выборки произошли на соединение.

Например, пользователь выполняет инструкцию FETCH из одного курсора, а затем вызывает хранимую процедуру, которая открывает и обрабатывает результаты из другого курсора. Когда управление возвращается от вызванной хранимой процедуры, @@FETCH_STATUS отражает последней инструкции FETCH, выполненной в хранимой процедуре, а не инструкции FETCH, выполненной прежде, чем была вызвана хранимая процедура.

Чтобы получить состояние последней выборки конкретного курсора, запросите fetch_status столбец sys.dm_exec_cursors функции динамического управления.

В следующем примере используется переменная @@FETCH_STATUS для управления действиями курсора в цикле WHILE .

Использование DBMS_SQL вместо динамического PL/SQL

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

И все же в некоторых ситуациях приходится использовать пакет DBMS_SQL . Эти ситуации описаны ниже.

Получение информации о столбцах запроса

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

При вызове этой программы необходимо объявить коллекцию PL/SQL на базе типа кол­лекции DBMS_SQL. DESC_TAB (или DESC_TAB2 , если запрос может возвращать имена столбцов, длина которых превышает 30 символов). После этого вы можете использовать методы коллекций для перебора таблицы и извлечения информации о курсоре. Следующий анонимный блок демонстрирует основные действия, выполняемые при работе с пакетом:

Чтобы упростить использование DESCRIBE_C0LUMNS , я создал пакет, который скрывает большинство технических подробностей и упрощает использование этой функциональ­ности. Спецификация пакета выглядит так:

Функция for_query используется в том случае, если вы хотите получить информацию о столбцах динамического запроса, но в остальном не собираетесь использовать DBMS_SQL . Использование пакета продемонстрировано в следующем сценарии:

Поддержка требований категории 4

Пакет DBMS_SQL поддерживает динамический SQL категории 4 (переменное количество столбцов или передаваемых параметров) более естественно, чем NDS . Вы уже видели, что для реализации категории 4 в NDS необходимо перейти на динамический PL/ SQL , а многие разработчики обычно стараются обойтись без этого высокого уровня абстракции.

Когда вы сталкиваетесь с категорией 4? Конечно, при построении интерфейсной части для поддержки несистематизированных запросов, генерируемых пользователями, или при построении обобщенной программы построения отчетов, которая динамически строит формат отчета и содержимое во время выполнения. Разберем одну из вариаций на эту тему: построение процедуры PL/SQL для вывода содержимого таблицы — любой таблицы, заданной пользователем во время выполнения. Здесь мы ограничимся рас­смотрением аспектов, относящихся непосредственно к динамическому SQL; за полной реализацией обращайтесь к файлу intab.sp на сайте книги.

Процедурный интерфейс

В своей реализации я буду использовать PL/SQL и DBMS_SQL . Но прежде чем браться за написание кода, необходимо создать спецификацию. Как будет вызываться эта процедура? Какую информацию должен предоставить пользователь (в данном случае разработчик)? Что должен ввести пользователь для получения желаемого вывода? В следующей таблице перечислены входные данные моей процедуры intab (сокращение от « in table »).

Параметр
Описание
Имя таблицы Обязательно (главная информация, используемая программой)
Секция WHERE Не обязательно. Позволяет ограничить строки, возвращаемые запрос. Если условие
не задано, возвращаются все строки. Параметр также может использоваться для
передачи условий ORDER BY и HAVING, следующих непосредственно за WHERE
Фильтр имен
столбцов
Не обязательно. Если вы не хотите выводить все столбцы таблицы, передайте список, разделенный запятыми; в этом случае будут использоваться только указанные
вами столбцы

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

Ниже приводятся примеры вызовов intab с результатами. Начнем с вывода всего со­держимого таблицы emp :

А теперь перейдем к работникам отдела 10, ограничивая максимальную длину текстовых столбцов 20 символами:

Переходим к совершенно другой таблице с другим количеством столбцов:

Обратите внимание: пользователю не приходится передавать информацию о структуре

таблицы. Моя программа получает эту информацию самостоятельно — собственно, имен­но эта особенность процедуры intab делает ее примером динамического SQL категории 4.

Последовательность построения intab


Вывод содержимого произвольной таблицы происходит по следующей схеме:

  1. Построение и разбор команды select (с использованием open_cursor и parse).
  2. Связывание всех локальных переменных с их «заместителями» в запросе (с ис­пользованием bind_variable).
  3. Определение каждого курсора для этого запроса (с использованием define_ column).
  4. Выполнение и выборка строк базы данных (с использованием execute и fetch_ rows).
  5. Получение значений из выбранной строки таблицы и их включение в выводимый текст (с использованием column_value). Затем строка выводится выводом проце­дуры put_line пакета dbms_output.

В настоящее время моя реализация intab не поддерживает привязку параметров в аргументе where_in, поэтому мы не будем подробно рассматривать код шага 2.

Построение SELECT

Чтобы извлечь данные из таблицы, необходимо построить команду SELECT . Структура этого запроса определяется различными входными данными процедуры (имя таблицы, условие WHERE и т. д.) и содержимым словаря данных. Помните, что пользователь не должен предоставлять список столбцов — вместо этого я должен идентифицировать столбцы таблицы и извлечь список из представления словаря данных. Я решил ис­пользовать представление ALL_TAB_COLUMNS процедуры intab, чтобы пользователь мог просматривать содержимое не только таблиц, владельцем которых он является (доступных в user_tab_columns), но и любых таблиц, для которых он обладает доступом select. Для получения информации о столбцах таблицы используется следующий курсор:

С этим курсором я получаю имя, тип данных и длину для каждого столбца таблицы. Как сохранить всю эту информацию в моей программе PL/SQL ?

  • Чтобы ответить на этот вопрос, необходимо подумать над тем, как эти данные будут использоваться. Как выясняется, у них есть много разных вариантов использова­ния — например:
  • Чтобы построить список выборки для запроса, я буду использовать имена столбцов.
  • Чтобы вывести содержимое таблицы в удобном виде, необходимо вывести над данными заголовки столбцов, которые должны быть размещены по горизонтали в правильных позициях. Следовательно, для каждого столбца необходимо знать имя и длину данных.
  • Чтобы осуществить выборку данных в динамическом курсоре, необходимо опреде­лить столбцы курсора вызовами DEFINE_COLUMN . Для этого нужно знать типы и длины данных.
  • Чтобы извлечь данные из выбранной строки с использованием COLUMN_VALUE , я дол­жен знать типы данных всех столбцов, а также их количество.
  • Чтобы вывести данные, я должен построить строку со всем данными (преобразуя числа и даты функцией TO_CHAR ). Данные необходимо дополнить по ширине для размещения под заголовками столбцов, как это было сделано в строке заголовка. Моя программа многократно использует информацию столбцов, однако повторных обращений к словарю данных хотелось бы избежать. Соответственно, при получении данных столбцов из представления ALL_TAB_COLUMNS я сохраню эти данные в трех разных коллекциях PL/SQL , описанных в следующей таблице.
Коллекция
Описание
colname Имена столбцов
coltype Типы данных столбцов (строки с описаниями типов)
collen Количество символов, необходимых для вывода данных столбца

Таким образом, для третьего столбца таблицы emp элемент colname(3) содержит строку «SAL», элемент coltype(3) содержит строку «NUMBER», а элемент collen(3) равен 7 и т. д.

Информация имени и типа данных берется прямо из словаря данных. С вычисле­нием длины столбца дело обстоит сложнее, но для написания динамического SQL категории 4 это не столь существенно. При желании читатель может изучить файл самостоятельно.

Вся логика применяется в цикле FOR с курсором, который перебирает все столбцы табли­цы (в соответствии с определением ALL_COLUMNS ). Этот цикл (приведенный в следующем примере) заполняет мою коллекцию PL/SQL :

После завершения цикла список выборки построен, коллекции PL/SQL заполнены информацией о столбцах, необходимой для вызовов DBMS_SQL . DEFINE_COLUMN и DBMS_SQL . COLUMN_VALUE , а также создана строка заголовка. Неплохо для одного цикла!

Теперь нужно разобрать запрос и построить разные столбцы объекта динамического курсора.

Определение структуры курсора

Фаза разбора достаточно тривиальна. Я просто собираю команду SQL из обработанных компонентов — прежде всего, из только что построенного списка столбцов (переменная col_list ):

Я не собираюсь ограничиться разбором — курсор нужно выполнить. Но перед этим не­обходимо его структурировать. В DBMS_SQL при открытии курсора вы всего лишь полу­чаете дескриптор для блока памяти. При разборе команды SQL эта команда связывается с упомянутой памятью. Однако необходимо сделать следующий шаг — определить столбцы в курсоре, чтобы он мог использоваться для хранения полученных данных. Для динамического SQL категории 4 этот процесс достаточно сложен. Я не могу жестко запрограммировать ни количество, ни типы вызовов DBMS_SQL.DEFINE_COLUMN в своей программе; часть информации появляется лишь на стадии выполнения. К счастью, в случае intab имеются коллекции с данными обо всех столбцах. Остается лишь создать вызов DBMS_SQL.DEFINE_COLUMN для каждого столбца, определенного в коллекции colname. Но прежде чем переходить к коду, стоит сказать пару слов о DBMS_SQL.DEFINE_COLUMN . Заголовок этой встроенной процедуры выглядит так:

При ее использовании следует учитывать три обстоятельства:

  • Во втором аргументе передается число. DBMS_SQL.DEFINE_COLUMN работает не с имена­ми столбцов, а с последовательными позициями столбцов в списке.
  • Третий аргумент задает тип данных столбца курсора. В нем передается выражение соответствующего типа. Иначе говоря, DBMS_SQL.DEFINE_COLUMN передается не строка (скажем, « VARCHAR2 »), а переменная, определенная с типом VARCHAR2 .
  • При определении столбца символьного типа необходимо задать максимальную длину значений, которые могут загружаться в курсор.

В контексте процедуры intab строка коллекции соответствует N-й позиции списка столбцов. Тип данных хранится в коллекции coltype, но его необходимо преобразовать в вызов DBMS_SQL.DEFINE_COLUMN с использованием соответствующей локальной пере­менной. Все это происходит в следующем цикле FOR :

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

где fdbk — объект обратной связи, возвращаемый при вызове EXECUTE .

Остается последний шаг: выборка данных и их форматирование для вывода.

Выборка и отображение данных

Я использую цикл FOR с курсором для получения каждой строки данных, идентифи­цированной моим динамическим курсором. Если текущей является первая строка, я вывожу заголовок (тем самым предотвращается вывод заголовка для запроса, не возвращающего данных). Для каждой полученной строки данных я генерирую строку результата и вывожу ее:

Текст с выводимыми значениями строится в цикле FOR . Встроенная функция DBMS_SQL. COLUMN_VALUE вызывается для каждого столбца в таблице (информация о котором хранится в моих коллекциях). Как видно из листинга, я использую функции is_* для определения типа столбца, а следовательно, и выбора переменной, которая получит значение.

После преобразования значения в строку (необходимого для дат и чисел) я дополняю его справа пробелами до нужной длины (хранящейся в коллекции collen), чтобы значение было выровнено по заголовкам столбцов:

Итак, в вашем распоряжении появляется универсальная процедура для вывода содержи­мого таблиц базы данных из программ PL/SQL . И снова за подробностями обращайтесь к файлу intab.sp; файл intab_dbms_sql.sp содержит версию этой процедуры, адаптированную для новых возможностей баз данных и более полно документированную.

Минимальный разбор динамических курсоров

Один из недостатков EXECUTE IMMEDIATE заключается в том, что при каждом выполне­нии динамическая строка обрабатывается заново, что обычно подразумевает разбор, оптимизацию и построение плана выполнения. Для большинства ситуаций, требующих применения динамического SQL, затраты на эти действия компенсируются другими преимуществами NDS (в частности, предотвращением вызовов PL/SQL API , необхо­димых для DBMS_SQL ). Однако в некоторых случаях разбор обходится слишком дорого, и тогда DMBS_SQL может оказаться лучшим решением.

При использовании DBMS_SQL можно явно обойти фазу разбора, если вы знаете, что в динамически исполняемой строке SQL изменяются только параметры. Для этого достаточно не вызывать заново, а ограничиться простой повторной подстановкой значений переменных вызовами DBMS_SQL.BIND_VARIABLE . Начнем с очень простого примера, демонстрирующего применение конкретных вызовов пакета DBMS_SQL .

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

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

Строки Описание
7 Получение курсора — обычного указателя на память, используемую DBMS_SQL
8-9 Разбор динамического курсора после присоединения единственного изменяемого
элемента (переменная i)
10 Выполнение запроса
11 Закрытие курсора

Все происходящее вполне допустимо (и конечно, обычно за выполнением запроса сле­дуют операции выборки), однако в целом DBMS_SQL используется неверно. Рассмотрим следующую модификацию тех же действий:

В этом варианте использования DBMS_SQL я объявляю курсор только один раз, потому что могу использовать его с каждым вызовом DBMS_SQL.PARSE . Я также перемещаю вызов разбора за пределы курсора. Поскольку структура команды SQL остается неизменной, курсор не нужно разбирать заново для каждого значения i. Итак, я выполняю разбор только один раз, после чего в цикле подставляю в курсор новое значение переменной и выполняю курсор. Когда все будет сделано (после завершения цикла), курсор закрывается. Возможность явного и раздельного выполнения каждого шага предоставляет разработ­чику невероятную гибкость (а заодно создает проблемы со сложностью кода DBMS_SQL ). Если вы стремитесь именно к этому, с DBMS_SQL трудно соперничать.

Если вы используете DBMS_SQL в своих приложениях, я рекомендую воспользоваться пакетом из файла dynalloc.pkg на сайте книги. Этот пакет помогает:

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

Новые возможности Oracle11g

В Oracle11g появились средства взаимодействия между встроенным динамическим SQL и DBMS_SQL: теперь вы можете пользоваться преимуществами обеих технологий, чтобы совместить оптимальное быстродействие с простейшей реализацией. А если говорить конкретно, появилась возможность преобразования курсоров DBMS_SQL в курсорные переменные, и наоборот.

Функция DBMS_SQL.TO_REFCURSOR

Функция DBMS_SQL.TO_REFCURSOR преобразует номер курсора (полученный вызовом DBMS_SQL.OPEN_CURSOR ) в слаботипизованную курсорную переменную (объявленную с типом SYS_REFCURSOR или слабым пользовательским типом REF CURSOR ). Далее вы мо­жете извлекать данные из курсорной переменной в локальные переменные или даже передать курсорную переменную во внешнюю среду для выборки данных.

Прежде чем передавать курсор SQL функции DBMS_SQL.TO_REFCURSOR , необходимо вы­звать для него OPEN, PARSE и EXECUTE ; в противном случае произойдет ошибка. После того как курсор будет преобразован, вы уже не сможете работать с ним средствами DBMS_SQL , в том числе и закрывать его. Все операции должны выполняться только через курсорную переменную.

Зачем нужна эта функция? Как упоминалось ранее, DBMS_SQL иногда оказывается предпо­чтительным или единственным решением для некоторых операций динамического SQL . Допустим, мы знаем, какие конкретные столбцы следует выбрать, но предложение WHERE запроса содержит неизвестное (на стадии компиляции) количество формальных параме­тров, что не позволяет использовать EXECUTE IMMEDIATE с фиксированной секцией USING . Реализация могла бы базироваться на DBMS_SQL от начала до конца, но использование DBMS_SQL для выборки строк и значений отдельных полей требует слишком большого объ­ема работы. Гораздо проще было бы использовать традиционную статическую выборку и даже BULK COLLECT . Именно такое решение продемонстрировано в следующем примере:

Другой пример ситуации, в которой может пригодиться эта функция: допустим, в про­грамме выполняется динамический SQL , требующий применения DBMS_SQL , но результат должен быть передан клиенту промежуточного уровня (например, приложению Java или .NET). Передать курсор DBMS_SQL невозможно, но ничто не мешает вернуть курсорную переменную.

Функция DBMS_SQL.TO_CURSOR

Функция DBMS_SQL.TO_CURSOR преобразует переменную REF CURSOR (сильно- или слаботи­пизованную) в номер курсора SQL, который затем может передаваться подпрограммам DBMS_SQL. Курсорная переменная должна быть открыта до ее передачи функции DBMS_SQL.TO_CURSOR .

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

Эта функция будет удобна в том случае, если количество подставляемых в команду SQL переменных известно во время компиляции, но вы не знаете количество элементов, участвующих в выборке (очередной пример динамического SQL категории 4!). Следующий пример демонстрирует ее практическое применение:

Усовершенствованная модель безопасности DBMS_SQL

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

В Oraclell для защиты от атак такого рода в пакете DBMS_SQL были введены три до­полнительные меры безопасности:

  • Генерирование непредсказуемых номеров курсоров.
  • Ограничение возможностей использования пакета DBMS_SQL при передаче недей­ствительного номера курсора.
  • Отказ в выполнении операции DBMS_SQL , если пользователь, пытающийся работать с курсором, отличен от пользователя, открывшего курсор.

Непредсказуемые номера курсоров

До выхода Oracle Database 11g , вызовы DBMS_SQL.OPEN_CURSOR возвращали последовательно увеличивающиеся числа (обычно из диапазона от 1 до 300). Такая предсказуемость могла позволить атакующему перебрать целые числа и проверить, не являются ли они номерами действительных, открытых курсоров. Обнаруженный курсор мог использоваться для атаки.

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

Отказ в доступе к DBMS_SQL при использовании недопустимого номера курсора (ORA-24971)

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

Рассмотрим следующий блок:

Здесь выполняется действительная команда UPDATE , которая «обновляет» salary теку­щим значением для всех строк таблицы employees в локальной процедуре set_salary. Я вызываю эту процедуру, затем пытаюсь выполнить недействительный курсор, после чего снова вызываю set_salary. Результаты выполнения этого блока:

Процедура set_salary сработала в первый раз, но после попытки выполнения недей­ствительного курсора при повторном запуске set_salary было инициировано исклю­чение ORA-29471 . Собственно, любая попытка вызова программы DBMS_SQL приведет к выдаче этой ошибки.

Восстановить доступ к DBMS_SQL можно только одним способом: выходом и повторным подключением. Да, жестко! Но это вполне разумно с учетом потенциально опасной ситуации, приведшей к ошибке.

База данных также блокирует доступ к DBMS_SQL , если программа, в которой был открыт курсор, инициировала исключение (которое может быть не связано с динамическим SQL). Если ошибка «поглощается» программой (то есть не инициируется заново), определить ее причину будет нелегко.

Запрет операций DBMS_SQL при изменении действующего пользователя (ORA-24970)

Oracle Database 11g предоставляет новую перегруженную версию функции OPEN_CURSOR с аргументом:

DBMS_SQL.OPEN_CURSOR (уровень_безопасности IN INTEGER ) RETURN INTEGER ;

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

  • 0 — отключение проверок безопасности для операций DBMS_SQL с курсором. Это озна­чает, что вы можете выполнить выборку из курсора, а затем выполнить подстановки и заново выполнить курсор с другим фактическим идентификатором пользователя
  • или ролью (отличными от действовавших на момент первого разбора). Этот уровень безопасности не действует по умолчанию.
  • 1 — фактические идентификаторы пользователя и роли вызывающей стороны DBMS_SQL для подстановки и выполнения операций с курсором должны совпадать с тем, которые действовали для вызывающей стороны при последней операции разбора с этим курсором.
  • 2 — фактические идентификаторы пользователя и роли вызывающей стороны DBMS_ SQL для всех операций подстановки, выполнения, определения, описания и выборки с курсором должны совпадать с тем, которые действовали для вызывающей стороны при последней операции разбора с этим курсором.

Пример возможных ошибок, обусловленных новыми проверками безопасности Oracle:

  1. Создайте процедуру user_cursor в схеме hr, как показано ниже. Обратите внима­ние: эта программа выполняется с правами создателя; это означает, что при вызове этой программы другой схемой текущим или фактическим пользователем ста­новится hr. Откройте курсор и разберите запрос для all_source с этим курсором. Затем верните номер курсора dbms_sql в аргументе out:

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

3. Подключитесь с правами scott. Запустите программу use_cursor из схемы hr с безопасностью уровня 2 и получите динамический курсор SQL. Наконец, по­пытайтесь выполнить этот курсор из схемы SCOTT :


Oracle выдает ошибку ORA-29470 , потому что курсор был открыт и разобран в схеме hr (из-за присутствия authid definer ), но выполнялся в схеме SCOTT .

Что такое код mssql_fetch_row

(PHP 3, PHP 4, PHP 5)

mssql_fetch_row — Get row as enumerated array

Description array mssql_fetch_row ( resource result )

Returns: An array that corresponds to the fetched row, or FALSE if there are no more rows.

mssql_fetch_row() fetches one row of data from the result associated with the specified result identifier. The row is returned as an array. Each result column is stored in an array offset, starting at offset 0.

Subsequent call to mssql_fetch_row() would return the next row in the result set, or FALSE if there are no more rows.

Замечание: Эта функция устанавливает NULL-поля в значение NULL PHP.

Пред. Начало След.
mssql_fetch_object Уровень выше mssql_field_length

Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:

Совместная работа PHP и MSSQL ч.2

Опубликовано Антон Миронов в 01.02.2020

В предыдущей части в результате запроса к БД был получен sqlsrv объект типа SQL Server Statement resource. Для его обработки существует функция sqlsrv_fetch_array(). Первым ее параметром является объект-ресурс, полученный на предыдущем шаге, а вторым можно указать какой массив нам нужно получить — ассоциативный (SQLSRV_FETCH_ASSOC), не ассоциативный( SQLSRV_FETCH_NUMERIC) или оба сразу ( SQLSRV_FETCH_BOTH — стоит по умолчанию).

Выполним следующий код:

В результате в переменной result получим что-то вроде такого:

Получился обычный ассоциативный массив, с которым можно дальше работать

Хранимые процедуры в sqlsrv

Хранимая процедура — объект базы данных, представляющий собой набор SQL-инструкций, который компилируется один раз и хранится на сервере. Это означает, что она может хранится отдельно на сервере и использоваться разными приложениями. Библиотека sqlsrv позволяет работать с такими процедурами.

Для выполнения хранимой процедуры используется та же функция sqlsrv_query(). В качестве второго параметра (запроса) ей необходимо передать следующую строку:

где $nameFunc — имя хранимой процедуры.

Представим, что у нас на сервере существует хранимая процедура get_users, которая возвращает всех пользователей. Для ее выполнения необходимо написать следующий код:

Хранимые процедуры с параметрами

Хранимые процедуры также могут содержать входные параметры. Так, например, наша процедура get_users может содержать входной параметр id, введя который можно получить пользователя с данным id. В передаче данных параметров поможет третий аргумент функции sqlsrv_query():

Результат этой хранимой процедуры будет записан в переменную $result.

Использование $ row = mssql_fetch_object прерывает вторую строку $?

Ситуация:

Я кодирование PHP (5.2.1) и хочу обработать результат MSSQL.

выбор и результат $ ret в порядке, я тестировал его несколько раз.

Вопрос:

мой код содержит $row = mssql_fetch_object ($ret); дважды, потому что я скопировать & вставить код. Как это:

первый var_dump($row); показывает действительный объект:

но второй var_dump($row); является boolean(false) .

Как это возможно? Включает ли mssql_fetch_object() значение $ ret? Я проверил оба результата $ ret, и они были такими же.

Что мне не хватает?

благодарит за вашу помощь.

Создан 07 янв. 15 2015-01-07 10:21:26 Tamerlane

fetch функции перемещает внутренний указатель каждый раз вызываемый.Если у вас есть только одна строка, первый вызов fetch_object будет возвращать первую строку, второй раз вызов будет возвращен false, поскольку больше нет потока, который будет извлечен. – Royal Bg 07 янв. 15 2015-01-07 10:24:07

получение false из операции выборки означает, что для извлечения данных больше нет данных. например ваш запрос возвратил только одну строку, и вы уже ее получили. – Marc B 07 янв. 15 2015-01-07 16:50:27

1 ответ

Это происходит потому, что вы уже принес объект, когда вы сделали первый

Если вы хотите использовать ту же строку просто использовать $ строку снова.

Функция mssql_fetch_object используется в то время как() заявление поэтому, когда он возвращает ложь это означает, что нет больше строк в результате.

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

Вы делаете SELECT, который возвращает 3 строки. И вы запустите следующий код:

Вы получите что-то вроде следующего

Потому что вы пытаетесь получить 4-ю строку, однако ваш результат имеет только 3 строки.

Таким образом, вместо того, чтобы делать предыдущий фрагмент кода, вы должны сделать что-то вроде этого:

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

Создан 07 янв. 15 2015-01-07 16:46:40 bucur89

Использование $ row = mssql_fetch_object прерывает вторую строку $? — php

Ситуация:

Я кодирую PHP (5.2.1) и хочу обработать результат mssql.

результат select и $ ret хорош, я тестировал его несколько раз.

Вопрос:

мой код содержит $row = mssql_fetch_object ( $ret ); дважды, потому что я копировал и вставлял какой-то код. Как это:

первый var_dump($row); показывает действительный объект:

но второй var_dump($row); boolean(false) .

Как это возможно? Включает ли mssql_fetch_object() значение $ ret? Я проверил оба результата $ ret, и они были такими же.

Что мне не хватает?

Спасибо за вашу помощь.

    2 1
  • 23 июл 2020 2020-07-23 02:26:22
  • Tamerlane

1 ответ

Это происходит потому, что вы уже набрали объект, когда вы сделали первый

Если вы хотите повторно использовать одну и ту же строку, просто используйте $ row снова.

Функция mssql_fetch_object используется в выражении while(), поэтому, когда она возвращает false, это означает, что в результате не осталось больше строк.

Быстрый пример.

Вы делаете SELECT, который возвращает 3 строки. И вы запускаете следующий код:

Вы получите следующее:

Потому что вы пытаетесь получить 4-ю строку, однако ваш результат имеет только 3 строки.

Поэтому вместо того, чтобы делать предыдущий фрагмент кода, вы должны сделать что-то вроде этого:

Поэтому, когда больше нет строк, вы выходите и вы продолжаете свой код, и вы получите что-то вроде следующего

Использование $ row = mssql_fetch_object прерывает вторую строку $?

Я кодирую PHP (5.2.1) и хочу обработать результат mssql.

результат select и $ ret хорош, я тестировал его несколько раз.

my code contains $row = mssql_fetch_object ( $ret ); twice because i copy & pasted some code. Like this:

первый var_dump ($ row); показывает действительный объект:

но второй var_dump ($ row); — boolean (false) .

Как это возможно? Включает ли mssql_fetch_object() значение $ ret? Я проверил оба результата $ ret, и они были такими же.

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