Перетворення VARCHAR у VARBINARY


17

Я зберігаю журнал дорогих запущених запитів разом з їх планами запитів у таблиці, щоб ми могли відстежувати тенденції в продуктивності та визначати області, які потребують оптимізації.

Однак дійшло до того, що плани запитів займають занадто багато місця (оскільки ми зберігаємо весь план проти кожного запиту).

Тому я намагаюся нормалізувати наявні дані, витягнувши QueryPlanHash та QueryPlan до іншої таблиці.

CREATE TABLE QueryPlans
(
    QueryPlanHash VARBINARY(25),
    QueryPlan XML,
    CONSTRAINT PK_QueryPlans PRIMARY KEY
    (
      QueryPlanHash
    )
);

Оскільки визначення query_plan_hashin sys.dm_exec_query_statsє двійковим полем (і я регулярно вставляю нові дані), я використовував VARBINARYдля типу даних у своїй новій таблиці.

Однак вставка нижче не вдається ...

INSERT INTO QueryPlans
    ( QueryPlanHash, QueryPlan )
SELECT queryplanhash, queryplan
FROM
(
    SELECT 
      p.value('(./@QueryPlanHash)[1]', 'varchar(20)') queryplanhash,
      QueryPlan,
      ROW_NUMBER() OVER (PARTITION BY p.value('(./@QueryPlanHash)[1]', 'varchar(20)') ORDER BY DateRecorded) rownum
    FROM table
    CROSS APPLY QueryPlan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple[@QueryPlanHash]') t(p)
) data
WHERE rownum = 1

.... з помилкою

Implicit conversion from data type varchar to varbinary is not allowed. Use the CONVERT function to run this query.

Проблема полягає в тому, що хеші плану запитів вже є у двійковому форматі, однак вони зберігаються як VARCHAR у Плані запитів XML, наприклад

0x9473FBCCBC01AFE

і CONVERT to BINARY надає зовсім інше значення

0x3078393437334642434342433031414645

Я спробував змінити визначення значення в XQuery select на бінарне, але потім воно не повернуло жодних значень.

Як я можу отримати значення 0x9473FBCCBC01AFEз плану запитів XML як a VARBINARY, а не як VARCHAR?

Відповіді:


28

Вам потрібно використовувати певний стиль, коли ви очікуєте збереження того ж бінарного значення при перетворенні з рядка. В іншому випадку SQL Server намагається кодувати рядок так само, як вона б кодувала 'bob'або 'frank'.

Однак це означає, що ваш рядок введення не виглядає правильним - відсутні або один байт, або один байт занадто багато. Це прекрасно спрацьовує, якщо я відміняю кінцевий E:

SELECT CONVERT(VARBINARY(25), '0x9473FBCCBC01AF', 1);
------------ the ,1 is important ---------------^^^

Результат двійковий:

----------------
0x9473FBCCBC01AF

1
Ах, ,1було те, чого мені не вистачало. Це було простіше, ніж я очікував! Спасибі!
Марк Сінкінсон

Не впевнений у відсутньому / зайвому байті. У записах 2666, які я маю, є 183, які не виходятьTRY_CONVERT
Марк Сінкінсон,

Можливо, потрібно додати символ (скажімо, 0) до будь-якого рядка з непарним числом символів. Це змінює значення, але завжди має змінювати те саме значення однаково (і я не підозрюю, що у вас будуть зіткнення з 0 або без нього).
Аарон Бертран

Це не помилка? Queryplanhash в xml явно встановлено на це значення ... Безумовно, a TRY_CONVERTдо a BINARYне повинен повертатисяNULL
Марк Сінкінсон

Від порівняння значень, збережених у моїй таблиці, з xml, це насправді 0, якого не вистачає. Отже значення повинно бути 0x09473FBCCBC01AF. Я можу виправити їх за допомогою простої ЗАМІНИ, але я впевнений, що це помилка ...
Марк Сінкінсон

0

Як я можу отримати значення 0x9473FBCCBC01AFE з плану запитів XML як VARBINARY, а не VARCHAR?

Я зіткнувся з чимось подібним, використовуючи HeidiSQL для запиту по таблицях CASD , і вирішив за допомогою fn_varbintohexstr () , наприклад:

SELECT master.dbo.fn_varbintohexstr(table.hexfield) FROM table;

Для HeidiSQL значення було неправильним, як "0x3F3F3F3F3F3F3F3F", і стало правильним, як "0x158B1DB75616484695684007CE98E21C".

OBS: працює з MSSQL 2008! Сподіваюся, це допомагає!


2
Зверніть увагу на застереження щодо використання fn_varbintohexstr() згаданих тут .
Ерік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.