Nano Hash - криптовалюты, майнинг, программирование

SQL-ошибка при выполнении оператора обновления с регулярным выражением через xmlquery на db2-luw

Дана таблица базы данных TABLE1 со столбцом COLUMN1 типа VARCHAR(1020). Мне нужно переформатировать некоторые данные из формата переменной длины в новый формат фиксированной длины (хэши удаляются, числа дополняются нулями до длины 10):

например: из "123#456#789" в "000000012300000004560000000789".

Выполнение данного sql-оператора приводит к следующему сообщению об ошибке, которое не очень полезно и указывает только на разрыв соединения:

Произошла ошибка при выполнении SQL-запроса

Ursache: SQL-Fehler [08001]: [jcc][t4][2030][11211][4.22.29] Bei Operationen auf dem der Verbindung zugrunde liegendem Socket, im Socketeingabedatenstrom oder Socketausgabedatenstrom ist ein Kommunikationsfehler aufgetreten.

Fehlerposition: Reply.fill() - недостаточно данных (-1). Nachricht: Unzureicende Daten. КОД ОШИБКИ=-4499, SQLSTATE=08001

Я работаю над базой данных DB2-LUW 11.1 v10.5.0.5, где регулярные выражения не поддерживаются, за исключением запросов xml.

Когда я заменяю второй оператор return на «return xs: string ($ COLUMN1)», оператор выполняется нормально. Так что это не похоже на синтаксическую ошибку.

Я нашел некоторую информацию о том, что порядок операторов let не фиксирован. Итак, я попытался удалить логику if/then/else, и это всегда приводило к одинаковым результатам, так что это тоже не проблема.

UPDATE TABLE1
SET COLUMN1 = xmlcast(xmlquery(
        '
        if (fn:matches( $COLUMN1,"(\d{0,10})#(\d{1,10})#(\d{1,10})")) 
            then
                xs:string($COLUMN1)
            else
                let $part1A := fn:replace($COLUMN1, "(\d{0,10})#(\d{1,10})#(\d{1,10})", "$1", "i")
                let $part1B := fn:string-join(("0000000000", $part1A), "")
                let $part1C := fn:substring($part1B, fn:string-length($part1B) - 9)

                let $part2A := fn:replace($COLUMN1, "(\d{0,10})#(\d{1,10})#(\d{1,10})", "$2", "i")
                let $part2B := fn:string-join(("0000000000", $part2A), "")
                let $part2C := fn:substring($part2B, fn:string-length($part2B) - 9)

                let $part3A := fn:replace($COLUMN1, "(\d{0,10})#(\d{1,10})#(\d{1,10})", "$3", "i")
                let $part3B := fn:string-join(("0000000000", $part3A), "")
                let $part3C := fn:substring($part3B, fn:string-length($part3B) - 9)

                let $result := fn:string-join(($part1C, $part2C, $part3C), "")

                return xs:string($result)
        '
        passing COLUMN1 AS "COLUMN1"
    ) AS VARCHAR(1020))
    WHERE COLUMN1 IS NOT NULL AND LENGTH(COLUMN1 ) > 0;

Ожидается, что обновление sql будет выполнено успешно, а не ошибка, которая приведет к разрыву соединения с базой данных.


Ответы:


1

Db2 11.1 поддерживает функции регулярных выражений вне функций XML.

E.g REGEXP_LIKE

https://www.ibm.com/support/knowledgecenter/en/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0061494.html

Итак, я бы использовал ОБНОВЛЕНИЕ на основе чего-то вроде этого

SELECT
   RIGHT('000000000' || REGEXP_EXTRACT(t,'(\d{0,10})#(\d{1,10})#(\d{1,10})',1,1,'',1),10)
|| RIGHT('000000000' || REGEXP_EXTRACT(t,'(\d{0,10})#(\d{1,10})#(\d{1,10})',1,1,'',2),10)
|| RIGHT('000000000' || REGEXP_EXTRACT(t,'(\d{0,10})#(\d{1,10})#(\d{1,10})',1,1,'',3),10)
FROM
    TABLE(VALUES('test123#456#789data')) AS T(T)

который возвращает

 1
 ------------------------------
 000000012300000004560000000789
21.10.2019
  • Я должен исправить свой вопрос относительно версии. В зависимости от этапа у меня есть разные версии db2, которые необходимо поддерживать. Наименьшая поддерживаемая версия — DB2 v10.5.0.5, поэтому встроенные функции регулярных выражений отсутствуют. 24.10.2019
  • ХОРОШО. Обратите внимание, что базовая поддержка Db1 10.5 заканчивается 30 апреля 2020 г. 24.10.2019
  • Кроме того, я бы посоветовал попытаться избежать процедурной логики в вашей версии XML. т.е. возможно, попробуйте воспроизвести мое предложение выше, но используя XML (или ваши собственные скомпилированные функции регулярных выражений developer.ibm.com/articles/ ) в качестве прямой замены REGEXP_EXTRACT. 24.10.2019
  • И если ваша ошибка приводит к нарушению соединения с базой данных, сообщите об этом в службу поддержки IBM. 24.10.2019

  • 2

    Вот решение, которое работает для меня.

    Первый шаг: проблема заключалась в том, что \d в fn.matches() работает, но не работает в fn:replace(). Мне пришлось заменить \d на [0-9].

    SELECT COLUMN1 AS SOURCE, xmlcast(xmlquery(
            '
            if (not(fn:matches( $COLUMN1,"(^\d{0,10})#(\d{1,10})#(\d{1,10})$"))) 
                then
                    xs:string($COLUMN1)
                else
                    let $part1A := fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$1", "i")
                    let $part1B := fn:string-join(("0000000000", $part1A), "")
                    let $part1C := fn:substring($part1B, fn:string-length($part1B) - 9)
    
                    let $part2A := fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$2", "i")
                    let $part2B := fn:string-join(("0000000000", $part2A), "")
                    let $part2C := fn:substring($part2B, fn:string-length($part2B) - 9)
    
                    let $part3A := fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$3", "i")
                    let $part3B := fn:string-join(("0000000000", $part3A), "")
                    let $part3C := fn:substring($part3B, fn:string-length($part3B) - 9)
    
                    let $result := fn:string-join(($part1C, $part2C, $part3C), "")
    
                    return xs:string($result)
            '
            passing COLUMN1 AS "COLUMN1"
        ) AS VARCHAR(1020)) AS REPLACEDBY
    FROM
        TABLE(VALUES('123#456#789'),('test123#456#789data')) AS TABLE1(COLUMN1);
    

    возвращается

    SOURCE              | REPLACEDBY
    ---------------------------------------------
    123#456#789         | 000000012300000004560000000789
    test123#456#789data | test123#456#789data
    

    Второй шаг: отказ от процедурной логики приводит к

    SELECT 
        COLUMN1 AS SOURCE,
        RIGHT('000000000' || xmlcast(xmlquery('fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$1", "i")' passing COLUMN1 AS "COLUMN1") AS VARCHAR(10)), 10)
        || RIGHT('000000000' || xmlcast(xmlquery('fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$2", "i")' passing COLUMN1 AS "COLUMN1") AS VARCHAR(10)), 10)
        || RIGHT('000000000' || xmlcast(xmlquery('fn:replace($COLUMN1, "([0-9]{0,10})#([0-9]{1,10})#([0-9]{1,10})", "$3", "i")' passing COLUMN1 AS "COLUMN1") AS VARCHAR(10)), 10)
        AS REPLACEDBY
    FROM
        TABLE(VALUES('123#456#789'),('test123#456#789data'),('0#0#0')) AS TABLE1(COLUMN1)
    WHERE 
        0 <> xmlcast(xmlquery('fn:matches($COLUMN1,"(^\d{0,10})#(\d{1,10})#(\d{1,10})$")' passing COLUMN1 AS "COLUMN1") AS INTEGER);
    

    возвращается

    SOURCE              | REPLACEDBY
    ---------------------------------------------
    123#456#789         | 000000012300000004560000000789
    0#0#0               | 000000000000000000000000000000
    
    30.10.2019
    Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..