Erstellen eines Index für ein berechnetes Feld: Zeichenfolge oder Binärdaten werden abgeschnitten

8

Ich habe eine Tabelle Foomit folgenden Feldern:

ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint)

Jetzt möchte ich einen Index für LongValue erstellen, damit ich leicht nach serialisierten Werten suchen kann, die Zahlen darstellen.

create nonclustered index IX_Foo on Foo(LongValue);

Was mir folgenden Fehler ausspuckt:

String oder Binärdaten würden abgeschnitten werden.

Ja, in SerializedValue sind Daten vorhanden. Aber was kann gebetet werden, indem ein Index für ein berechnetes Feld erstellt wird?

Shaul Behr
quelle

Antworten:

8

Der Fehler wird nicht durch das Erstellen des Index verursacht. Der Fehler wird dadurch verursacht, TRY_CASTdass die berechneten Spaltenwerte bei der Indexerstellung ausgewertet werden.

Wenn ich das mache:

SELECT TRY_CAST(REPLICATE(CONVERT(nvarchar(MAX), N'a'), 4001) AS bigint)

Ich bekomme den gleichen Fehler.

Die Dokumentation sagt (Hervorhebung von mir):

Wenn die Umwandlung erfolgreich ist, gibt TRY_CAST den Wert als angegebenen Datentyp zurück. Wenn ein Fehler auftritt, wird null zurückgegeben. Allerdings , wenn Sie eine Konvertierung anfordern , die nicht explizit erlaubt ist, dann scheitert TRY_CAST mit einem Fehler.

Nun, es ist nicht genau klar , welche unter Fällen es mit einem Fehler fehl (scheint Art von asinine den ganzen gegebenen Punkt der Funktion, aber trotzdem ...), so dass wir den Code durch Transformation des Eingangswertes reparieren können (Verwendung etwas angemessen für die Daten in Ihrer Tabelle), da keine große Zeichenfolge verarbeitet werden muss, wenn sie ohnehin nicht in eine Bigint passt:

SELECT TRY_CAST(LEFT(REPLICATE(CONVERT(nvarchar(MAX), N'1'), 4001), 100) AS bigint)

Dies wird zurückgegeben, NULLda der Wert nicht gültig ist, aber nicht mit einem Fehler bombardiert wird.

Jon Seigel
quelle
-1

Wenn Sie eine Zeichenfolge mit einem zu langen Wert haben, schlägt die Indexerstellung fehl. Ich habe einen kleinen Testcode mit SQL Server 2012 ausprobiert.

CREATE TABLE dbo.foo 
(ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint));

INSERT INTO dbo.foo (serializedvalue) VALUES(REPLICATE(' ', 4000)+'1');

CREATE INDEX GotToTry ON foo(LongValue);

DROP TABLE dbo.foo;
GO

Mein schnelles Experiment hat gezeigt, dass der Code funktioniert, solange der nvarchar (max) -Wert 4000 Zeichen oder weniger beträgt. (Natürlich werden alle Leerzeichen mit nichts am Ende zu keinen Zeichen zusammengefasst und funktionieren daher einwandfrei.) Das 4001. Zeichen löst die String or binary data would be truncatedNachricht aus. Sie können Ihre Daten also auf einen SerializedValue untersuchen, der länger als 4000 Zeichen ist.

EDIT: Ja, die Konvertierung erfolgt in a BIGINT. Das Problem ist nicht das BIGINT, sondern das NVARCHAR(MAX). Zum Beispiel:

  1. Wenn eine Zeile '1111111111111111111' enthält, wird sowohl CREATE INDEXder Wert als auch der Wert in konvertiert BIGINT.
  2. Wenn eine Zeile 0 bis 4000 '1 ist, kann dies CREATE INDEXder Fall sein, der Wert kann jedoch sein, NULLda sie überläuft BIGINT.
  3. Wenn eine Zeile länger als 4000 Zeichen ist, CREATE INDEXschlägt die fehl.

Es scheint also, dass der tatsächliche Inhalt des NVARCHAR (MAX) für den CREATE INDEX von Bedeutung ist.

BEARBEITEN: Jon Seigel hat festgestellt, dass TRY_CAST den Fehler beim Erstellen des Index auslöst, wenn die Zeichenfolge länger als nvarchar (4000) ist.

RLF
quelle
2
Dies beantwortet die Frage nicht wirklich. Der Index ist auf einem Bigint. Es wird nie etwas anderes als ein Bigint sein. Die Frage ist, warum Daten abgeschnitten werden, wenn ein Bigint weit innerhalb der zulässigen Größe für einen Index liegt
Mark Sinkinson
1
@MarkSinkinson Bearbeitet, um weitere Details bereitzustellen. Das Problem ist der NVARCHAR (MAX) -Inhalt.
RLF