Konvertieren einer VARCHAR in eine VARBINARY

17

Ich habe ein Protokoll der teuren laufenden Abfragen zusammen mit ihren Abfrageplänen in einer Tabelle geführt, damit wir Leistungstrends überwachen und Bereiche identifizieren können, die optimiert werden müssen.

Es ist jedoch so weit, dass die Abfragepläne zu viel Speicherplatz beanspruchen (da der gesamte Plan für jede Abfrage gespeichert wird).

Ich versuche daher, die vorhandenen Daten zu normalisieren, indem ich QueryPlanHash und QueryPlan in eine andere Tabelle extrahiere.

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

Da die Definition des query_plan_hashin sys.dm_exec_query_statsein binäres Feld ist (und ich regelmäßig neue Daten eingefügt sein werden), war ich mit VARBINARYfür den Datentyp in meinem neuen Tisch.

Die folgende Einfügung schlägt jedoch fehl ...

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

.... mit dem Fehler

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

Das Problem ist, dass die Abfrageplan-Hashes bereits im Binärformat vorliegen, jedoch als VARCHAR im XML-Abfrageplan gespeichert sind, z

0x9473FBCCBC01AFE

und CONVERT to BINARY ergibt einen völlig anderen Wert

0x3078393437334642434342433031414645

Ich habe versucht, die Wertedefinition in der XQuery-Auswahl in "Binär" zu ändern, aber dann wurden keine Werte zurückgegeben.

Wie würde ich den Wert von 0x9473FBCCBC01AFEaus einem XML-Abfrageplan VARBINARYeher als als extrahieren VARCHAR?

Mark Sinkinson
quelle

Antworten:

28

Sie müssen einen bestimmten Stil verwenden, wenn Sie beim Konvertieren aus einer Zeichenfolge denselben Binärwert beibehalten möchten. Andernfalls versucht SQL Server, die Zeichenfolge auf die gleiche Weise zu codieren wie 'bob'oder 'frank'.

Ihre Eingabezeichenfolge sieht jedoch nicht korrekt aus - es fehlt entweder ein Byte oder ein Byte zu viele. Das funktioniert gut, wenn ich das Trailing fallen lasse E:

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

Ergebnis ist binär:

----------------
0x9473FBCCBC01AF
Aaron Bertrand
quelle
1
Ah, das hat ,1mir gefehlt. Das war einfacher als ich erwartet hatte! Vielen Dank!
Mark Sinkinson
Nicht sicher über das fehlende / zusätzliche Byte. In den 2666 Aufzeichnungen, die ich habe, gibt es 183, die den Fehler machenTRY_CONVERT
Mark Sinkinson
Möglicherweise muss ein Zeichen (z. B. 0) an eine Zeichenfolge mit einer ungeraden Anzahl von Zeichen angehängt werden. Das ändert den Wert, sollte aber immer den gleichen Wert auf die gleiche Weise ändern (und ich vermute nicht, dass Sie Kollisionen mit oder ohne die 0 haben werden).
Aaron Bertrand
Ist das nicht ein Bug? Der queryplanhash in der XML wird explizit auf diesen Wert gesetzt ... Sicherlich sollte ein TRY_CONVERTto a BINARYnicht zurückkehrenNULL
Mark Sinkinson
Beim Vergleich der in meiner Tabelle gespeicherten Werte mit der XML-Datei fehlt tatsächlich eine führende 0. Der Wert sollte also 0x09473FBCCBC01AF sein. Ich kann das mit einem einfachen REPLACE beheben, aber ich bin sicher, es ist ein Fehler ...
Mark Sinkinson
0

Wie extrahiere ich den Wert von 0x9473FBCCBC01AFE aus einem XML-Abfrageplan als VARBINARY und nicht als VARCHAR?

Ich sah mich so etwas mit HeidiSQL zum Abfragen von CASD-Tabellen gegenüber und löste es mit fn_varbintohexstr () wie folgt :

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

Bei HeidiSQL war der Wert wie "0x3F3F3F3F3F3F3F3F3F" falsch und wurde wie "0x158B1DB75616484695684007CE98E21C" korrekt.

OBS: Funktioniert seit MSSQL 2008! Ich hoffe es hilft!

MMJ
quelle
2
Beachten Sie die fn_varbintohexstr() hier genannten Vorsichtsmaßnahmen .
Erik