Spec-Zone.ru › MySQL 8.4

14.11 Функции XML

Таблица 14.16 Функции XML

Таблица 14.16 Функции XML
Имя Описание
ExtractValue() Извлечение значения из XML-строки с помощью XPath
UpdateXML() Возвращает заменённый фрагмент XML

В этом разделе рассматриваются XML и связанные с ним возможности в MySQL.

Примечание

Получить XML-форматированный вывод из MySQL можно в клиентах mysql и mysqldump, вызвав их с опцией --xml. См. Раздел 6.5.1, «mysql — Клиент командной строки MySQL» и Раздел 6.5.4, «mysqldump — Программа резервного копирования базы данных».

Доступны две функции, предоставляющие основные возможности XPath 1.0 (XML Path Language, версия 1.0). В дальнейшем в этом разделе приводится некоторая базовая информация об синтаксисе и использовании XPath, однако подробное обсуждение этих тем выходит за рамки данного руководства, и для получения определённой информации вы должны обратиться к стандарту XML Path Language (XPath) 1.0. Полезным ресурсом для тех, кто только знакомится с XPath или хочет освежить свои знания основ, является учебник XPath на сайте Zvon.org, который доступен на нескольких языках.

Примечание

Эти функции находятся в стадии разработки. Мы продолжаем совершенствовать эти и другие аспекты функций XML и XPath в MySQL 8.4 и далее. Вы можете обсудить их, задавать вопросы о них и получить помощь от других пользователей в форуме пользователей MySQL XML.

XPath-выражения, используемые с этими функциями, поддерживают пользовательские переменные и локальные переменные хранимых программ. Пользовательские переменные слабо проверяются; переменные, локальные для хранимых программ, проверяются строго (см. также ошибку #26518):

  • Пользовательские переменные (слабая проверка). Переменные, использующие синтаксис $@variable_name (то есть, пользовательские переменные), не проверяются. Сервер не выдает предупреждений или ошибок, если переменная имеет неправильный тип или ранее не была присвоена значение. Это также означает, что пользователь полностью несёт ответственность за любые ошибки в написании, так как не выдаются предупреждения, если (например) $@myvairable используется вместо $@myvariable.

    Пример:

    mysql> SET @xml = '<a><b>X</b><b>Y</b></a>';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET @i =1, @j = 2;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @i, ExtractValue(@xml, '//b[$@i]');
    +------+--------------------------------+
    | @i   | ExtractValue(@xml, '//b[$@i]') |
    +------+--------------------------------+
    |    1 | X                              |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT @j, ExtractValue(@xml, '//b[$@j]');
    +------+--------------------------------+
    | @j   | ExtractValue(@xml, '//b[$@j]') |
    +------+--------------------------------+
    |    2 | Y                              |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT @k, ExtractValue(@xml, '//b[$@k]');
    +------+--------------------------------+
    | @k   | ExtractValue(@xml, '//b[$@k]') |
    +------+--------------------------------+
    | NULL |                                |
    +------+--------------------------------+
    1 row in set (0.00 sec)
    
  • Переменные в хранимых программах (сильная проверка). Переменные, использующие синтаксис $variable_name, можно объявлять и использовать с этими функциями, когда они вызываются внутри хранимых программ. Такие переменные локальны для хранимой программы, в которой они определены, и их тип и значение проверяются строго.

    Пример:

    mysql> DELIMITER |
    
    mysql> CREATE PROCEDURE myproc ()
        -> BEGIN
        ->   DECLARE i INT DEFAULT 1;
        ->   DECLARE xml VARCHAR(25) DEFAULT '<a>X</a><a>Y</a><a>Z</a>';
        ->
        ->   WHILE i < 4 DO
        ->     SELECT xml, i, ExtractValue(xml, '//a[$i]');
        ->     SET i = i+1;
        ->   END WHILE;
        -> END |
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> DELIMITER ;
    
    mysql> CALL myproc();
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 1 | X                            |
    +--------------------------+---+------------------------------+
    1 row in set (0.00 sec)
    
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 2 | Y                            |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)
    
    +--------------------------+---+------------------------------+
    | xml                      | i | ExtractValue(xml, '//a[$i]') |
    +--------------------------+---+------------------------------+
    | <a>X</a><a>Y</a><a>Z</a> | 3 | Z                            |
    +--------------------------+---+------------------------------+
    1 row in set (0.01 sec)
    

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

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

Примечание

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

  • ExtractValue(xml_frag, xpath_expr)

    ExtractValue() принимает два строковых аргумента, фрагмент XML-разметки xml_frag и XPath-выражение xpath_expr (также известный как локатоp); она возвращает текст (CDATA) первого текстового узла, являющегося дочерним элементом элемента или элементов, соответствующих XPath-выражению.

    Использование этой функции эквивалентно выполнению соответствия с использованием xpath_expr после добавления /text(). Другими словами, ExtractValue('<a><b>Sakila</b></a>', '/a/b') и ExtractValue('<a><b>Sakila</b></a>', '/a/b/text()') дают одинаковый результат. Если xml_frag или xpath_expr равна NULL, функция возвращает NULL.

    Если найдено несколько совпадений, содержимое первого дочернего текстового узла каждого соответствующего элемента возвращается (в порядке соответствия) как одна строка, разделённая пробелами.

    Если для выражения не найден ни один соответствующий текстовый узел (включая неявное /text())—по любой причине, при условии, что xpath_expr является корректным, и xml_frag состоит из элементов, которые правильно вложены и закрыты — возвращается пустая строка. Различия между соответствием по пустому элементу и полным отсутствием соответствия не делается. Это сделано по умолчанию.

    Если вам нужно определить, не найдено ли соответствующего элемента в xml_frag или такой элемент найден, но не содержит дочерних текстовых узлов, вы должны проверить результат выражения, использующего XPath-функцию count(). Например, оба этих утверждения возвращают пустую строку, как показано здесь:

    mysql> SELECT ExtractValue('<a><b/></a>', '/a/b');
    +-------------------------------------+
    | ExtractValue('<a><b/></a>', '/a/b') |
    +-------------------------------------+
    |                                     |
    +-------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue('<a><c/></a>', '/a/b');
    +-------------------------------------+
    | ExtractValue('<a><c/></a>', '/a/b') |
    +-------------------------------------+
    |                                     |
    +-------------------------------------+
    1 row in set (0.00 sec)
    

    Однако вы можете определить, был ли на самом деле соответствующий элемент, используя следующее:

    mysql> SELECT ExtractValue('<a><b/></a>', 'count(/a/b)');
    +-------------------------------------+
    | ExtractValue('<a><b/></a>', 'count(/a/b)') |
    +-------------------------------------+
    | 1                                   |
    +-------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue('<a><c/></a>', 'count(/a/b)');
    +-------------------------------------+
    | ExtractValue('<a><c/></a>', 'count(/a/b)') |
    +-------------------------------------+
    | 0                                   |
    +-------------------------------------+
    1 row in set (0.01 sec)
    
    Важно

    ExtractValue() возвращает только CDATA и не возвращает какие-либо теги, которые могут содержаться в соответствующем теге, ни их содержимое (см. возвращаемый результат как val1 в следующем примере).

    mysql> SELECT
        ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1,
        ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2,
        ->   ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3,
        ->   ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4,
        ->   ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;
    
    +------+------+------+------+---------+
    | val1 | val2 | val3 | val4 | val5    |
    +------+------+------+------+---------+
    | ccc  | ddd  | ddd  |      | ddd eee |
    +------+------+------+------+---------+
    

    Эта функция использует текущую сортировку SQL для сравнения со contains(), выполняя ту же агрегацию сортировки, что и другие строковые функции (такие как CONCAT()), учитывая сортировочную приводимость их аргументов; см. Раздел 12.8.4, «Приводимость сортировки в выражениях» для объяснения правил, регулирующих это поведение.

    (Ранее всегда использовалось двоичное сравнение — то есть, чувствительное к регистру.)

    NULL возвращается, если xml_frag содержит элементы, которые не правильно вложены или закрыты, и генерируется предупреждение, как показано в этом примере:

    mysql> SELECT ExtractValue('<a>c</a><b', '//a');
    +-----------------------------------+
    | ExtractValue('<a>c</a><b', '//a') |
    +-----------------------------------+
    | NULL                              |
    +-----------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1525
    Message: Incorrect XML value: 'parse error at line 1 pos 11:
             END-OF-INPUT unexpected ('>' wanted)'
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue('<a>c</a><b/>', '//a');
    +-------------------------------------+
    | ExtractValue('<a>c</a><b/>', '//a') |
    +-------------------------------------+
    | c                                   |
    +-------------------------------------+
    1 row in set (0.00 sec)
    
  • UpdateXML(xml_target, xpath_expr, new_xml)

    Эта функция заменяет одну часть заданного фрагмента XML-разметки xml_target новым XML-фрагментом new_xml, а затем возвращает изменённый XML. Часть xml_target, которая заменяется, соответствует XPath-выражению xpath_expr, предоставленному пользователем.

    Если не найдено ни одного выражения, соответствующего xpath_expr, или если найдено несколько совпадений, функция возвращает исходный xml_target XML-фрагмент. Все три аргумента должны быть строками. Если любой из аргументов для UpdateXML() является NULL, функция возвращает NULL.

    mysql> SELECT
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
        ->   UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4,
        ->   UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5
        -> \G
    
    *************************** 1. row ***************************
    val1: <e>fff</e>
    val2: <a><b>ccc</b><d></d></a>
    val3: <a><e>fff</e><d></d></a>
    val4: <a><b>ccc</b><e>fff</e></a>
    val5: <a><d></d><b>ccc</b><d></d></a>
    
Примечание

Подробное обсуждение синтаксиса и использования XPath выходит за рамки данного руководства. Для получения точной информации обратитесь к спецификации XML Path Language (XPath) 1.0. Полезным ресурсом для тех, кто только знакомится с XPath или хочет освежить свои знания основ, является учебник XPath на сайте Zvon.org, который доступен на нескольких языках.

Ниже приведены описания и примеры некоторых основных XPath-выражений:

  • /tag

    Совпадает с <tag/> только в том случае, если <tag/> является корневым элементом.

    Пример: /a соответствует <a><b/></a>, потому что он соответствует самому внешнему (корневому) тегу. Он не соответствует внутреннему элементу a в <b><a/></b>, так как в этом случае он является потомком другого элемента.

  • /tag1/tag2

    Совпадает с <tag2/> только в том случае, если он является потомком <tag1/>, и <tag1/> является корневым элементом.

    Пример: /a/b соответствует элементу b в фрагменте XML <a><b/></a>, потому что он является потомком корневого элемента a. Он не соответствует <b><a/></b>, так как в этом случае b является корневым элементом (и, следовательно, не является потомком другого элемента). Выражение XPath также не соответствует <a><c><b/></c></a>; здесь b является потомком a, но не является потомком a.

    Данный конструкт можно расширить до трех или более элементов. Например, выражение XPath /a/b/c соответствует элементу c во фрагменте <a><b><c/></b></a>.

  • //tag

    Совпадает с любой инстанцией <tag>.

    Пример: //a соответствует элементу a в любом из следующих фрагментов: <a><b><c/></b></a>; <c><a><b/></a></b>; <c><b><a/></b></c>.

    // может быть объединен с /. Например, //a/b соответствует элементу b в любом из фрагментов <a><b/></a> или <c><a><b/></a></c>.

    Примечание

    //tag эквивалентно /descendant-or-self::*/tag. Распространённая ошибка состоит в том, чтобы путать это с /descendant-or-self::tag, хотя последнее выражение может привести к совершенно другим результатам, как показано здесь:

    mysql> SET @xml = '<a><b><c>w</c><b>x</b><d>y</d>z</b></a>';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT @xml;
    +-----------------------------------------+
    | @xml                                    |
    +-----------------------------------------+
    | <a><b><c>w</c><b>x</b><d>y</d>z</b></a> |
    +-----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '//b[1]');
    +------------------------------+
    | ExtractValue(@xml, '//b[1]') |
    +------------------------------+
    | x z                          |
    +------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '//b[2]');
    +------------------------------+
    | ExtractValue(@xml, '//b[2]') |
    +------------------------------+
    |                              |
    +------------------------------+
    1 row in set (0.01 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');
    +---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[1]') |
    +---------------------------------------------------+
    | x z                                               |
    +---------------------------------------------------+
    1 row in set (0.06 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');
    +---------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::*/b[2]') |
    +---------------------------------------------------+
    |                                                   |
    +---------------------------------------------------+
    1 row in set (0.00 sec)
    
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');
    +-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[1]') |
    +-------------------------------------------------+
    | z                                               |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');
    +-------------------------------------------------+
    | ExtractValue(@xml, '/descendant-or-self::b[2]') |
    +-------------------------------------------------+
    | x                                               |
    +-------------------------------------------------+
    1 row in set (0.00 sec)
    
  • Оператор * действует как «подстановочный символ», который соответствует любому элементу. Например, выражение /*/b соответствует элементу b в любом из следующих фрагментов XML: <a><b/></a> или <c><b/></c>. Однако выражение не соответствует фрагменту <b><a/></b>, так как b должен быть потомком некоторого другого элемента. Подстановочный символ может быть использован в любом месте: выражение /*/b/* соответствует любому потомку элемента b, который сам по себе не является корневым элементом.

  • Вы можете сопоставить любой из нескольких локеров, используя оператор | (UNION). Например, выражение //b|//c соответствует всем элементам b и c в целевом XML.

  • Также можно сопоставить элемент на основе значения одного или нескольких его атрибутов. Это делается с использованием синтаксиса tag[@attribute="value"]. Например, выражение //b[@id="idB"] соответствует второму элементу b во фрагменте <a><b id="idA"/><c/><b id="idB"/></a>. Чтобы сопоставить любой элемент, имеющий attribute="value", используйте выражение XPath //*[attribute="value"].

    Для фильтрации нескольких значений атрибутов просто используйте несколько условий сравнения атрибутов последовательно. Например, выражение //b[@c="x"][@d="y"] соответствует элементу <b c="x" d="y"/>, встречающемуся где угодно в заданном фрагменте XML.

    Чтобы найти элементы, для которых один и тот же атрибут соответствует одному из нескольких значений, можно использовать несколько локеров, соединённых оператором |. Например, чтобы сопоставить все элементы b, чьи атрибуты c имеют одно из значений 23 или 17, используйте выражение //b[@c="23"]|//b[@c="17"]. Для этой цели также можно использовать логический оператор or: //b[@c="23" or @c="17"].

    Примечание

    Разница между or и | заключается в том, что or объединяет условия, а | объединяет наборы результатов.

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

  • Сравнение наборов узлов (например, '/a/b[@c=@d]') не поддерживается.

  • Все стандартные операторы сравнения XPath поддерживаются. (Ошибка #22823)

  • Выражения относительных локеров разрешаются в контексте корневого узла. Например, рассмотрите следующее запрос и результат:

    mysql> SELECT ExtractValue(
        ->   '<a><b c="1">X</b><b c="2">Y</b></a>',
        ->    'a/b'
        -> ) AS result;
    +--------+
    | result |
    +--------+
    | X Y    |
    +--------+
    1 row in set (0.03 sec)
    

    В этом случае локатор a/b разрешается в /a/b.

    Относительные локеры также поддерживаются внутри предикатов. В следующем примере d[../@c="1"] разрешается как /a/b[@c="1"]/d:

    mysql> SELECT ExtractValue(
        ->      '<a>
        ->        <b c="1"><d>X</d></b>
        ->        <b c="2"><d>X</d></b>
        ->      </a>',
        ->      'a/b/d[../@c="1"]')
        -> AS result;
    +--------+
    | result |
    +--------+
    | X      |
    +--------+
    1 row in set (0.00 sec)
    
  • Локеры, префиксные выражениями, которые вычисляются как скалярные значения (включая ссылки на переменные, литералы, числа и вызовы скалярных функций), не допускаются и приводят к ошибке.

  • Оператор :: не поддерживается в сочетании с типами узлов, такими как следующие:

    • axis::comment()

    • axis::text()

    • axis::processing-instructions()

    • axis::node()

    Однако тесты имени (такие как axis::name и axis::*) поддерживаются, как показано в этих примерах:

    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b');
    +-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b') |
    +-------------------------------------------------------+
    | x                                                     |
    +-------------------------------------------------------+
    1 row in set (0.02 sec)
    
    mysql> SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*');
    +-------------------------------------------------------+
    | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*') |
    +-------------------------------------------------------+
    | x y                                                   |
    +-------------------------------------------------------+
    1 row in set (0.01 sec)
    
  • «Вверх-вниз» навигация не поддерживается в случаях, когда путь приведёт «выше» корневого элемента. То есть, нельзя использовать выражения, которые соответствуют потомкам предков данного элемента, где один или несколько предков текущего элемента также являются предками корневого элемента (см. ошибку #16321).

  • Следующие функции XPath не поддерживаются или имеют известные проблемы, как указано:

      ```
//user[login/text()='neapolitan' and password/text()='1c3cr34m']/attribute::id

Это эквивалент XPath для SQL-запроса, такого как этот:

SELECT id FROM users WHERE login='neapolitan' AND password='1c3cr34m';

PHP-приложение, использующее XPath, может обрабатывать процесс входа в систему следующим образом:

<?php

  $file     =   "users.xml";

  $login    =   $POST["login"];
  $password =   $POST["password"];

  $xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id";

  if( file_exists($file) )
  {
    $xml = simplexml_load_file($file);

    if($result = $xml->xpath($xpath))
      echo "You are now logged in as user $result[0].";
    else
      echo "Invalid login name or password.";
  }
  else
    exit("Failed to open $file.");

?>

Проверки входных данных не выполняются. Это означает, что злоумышленник может «сократить» тест, введя ' or 1=1 и для имени пользователя, и для пароля, что приведет к тому, что $xpath будет вычислено следующим образом:

//user[login/text()='' or 1=1 and password/text()='' or 1=1]/attribute::id

Поскольку выражение в квадратных скобках всегда вычисляется как true, оно фактически эквивалентно выражению, которое сопоставляет атрибут id каждого элемента user в документе XML:

//user/attribute::id

Один из способов обойти эту атаку — просто заключить в кавычки имена переменных, которые нужно интерполировать в определении $xpath, заставляя значения, передаваемые с веб-формы, преобразовываться в строки:

$xpath = "//user[login/text()='$login' and password/text()='$password']/attribute::id";

Это та же стратегия, которая часто рекомендуется для предотвращения атак SQL-инъекции. В общем, практики, которые следует соблюдать для предотвращения атак XPath-инъекции, аналогичны практикам для предотвращения SQL-инъекций:

  • Никогда не принимайте непроверенные данные от пользователей в своем приложении.

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

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

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

Так же, как атаки SQL-инъекции могут использоваться для получения информации о схемах баз данных, атаки XPath-инъекции могут использоваться для обхода файлов XML для выявления их структуры, как обсуждается в статье Амита Клейна Blind XPath Injection (PDF-файл, 46 КБ).

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

mysql> SELECT ExtractValue(
    ->     LOAD_FILE('users.xml'),
    ->     '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
    -> ) AS id;
+-------------------------------+
| id                            |
+-------------------------------+
| 00327 13579 02403 42354 28570 |
+-------------------------------+
1 row in set (0.01 sec)

Поскольку ExtractValue() возвращает несколько совпадений в виде одной строки, разделенной пробелами, эта атака инъекции предоставляет каждому валидному идентификатору, содержащемуся в users.xml, пользователю в виде одной строки вывода. В качестве дополнительной меры предосторожности вы также должны проверить выходные данные перед отправкой их пользователю. Вот простой пример:

mysql> SELECT @id = ExtractValue(
    ->     LOAD_FILE('users.xml'),
    ->     '//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT IF(
    ->     INSTR(@id, ' ') = 0,
    ->     @id,
    ->     'Unable to retrieve user ID')
    -> AS singleID;
+----------------------------+
| singleID                   |
+----------------------------+
| Unable to retrieve user ID |
+----------------------------+
1 row in set (0.00 sec)

В общем, правила возврата данных пользователям безопасно аналогичны правилам приема данных от пользователя. Они могут быть сформулированы следующим образом:

  • Всегда проверяйте выходные данные на тип и допустимые значения.

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

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/xml-functions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API