2012-02-24 10 views
9

Próbuję użyć CONTEXT_INFO zdać userCode z procedury przechowywanej na spuście DELETE dla celów kontrolnych stół.Casting CONTEXT_INFO do varchar i uzyskaną długość

Wszystko działa dobrze, jednak zauważyłem, że długość kodu użytkownika zapisana w tabeli kontroli nie była poprawna.

Weź ten skrypt jako przykład ...

declare @userCode varchar(50) 
set @userCode = 'TestUser' 

declare @binary_userCode varbinary(128) 
set @binary_userCode = cast(@userCode as varbinary(128)) 
set CONTEXT_INFO @binary_userCode 

declare @temp_userCode varchar(50) 
set @temp_userCode = (select cast(CONTEXT_INFO() as varchar(50))) 

--set @temp_userCode = rtrim(ltrim(@temp_userCode)) 

select @userCode, len(@userCode), @temp_userCode, len(@temp_userCode) 

set CONTEXT_INFO 0x 

Wyniki:

len (@userCode) = 8

len (@temp_userCode) = 50

Dlaczego zmienna @temp_userCode wraca z długością 50, i jak mogę ją przyciąć z powrotem do jej oryginalnej długości Ctly?

Dalsze informacje:

Uruchamianie SQL Server 2005, jednakże rozwiązanie musi działać we wszystkich wersjach od 2005 r.

Odpowiedz

6

Kiedy przypisany CONTEXT_INFO robi wyściełane się z zerowym bajtów 0x00 do 128 bajtów długości i staje 0x5465737455736572000000...

Można użyć

REPLACE(CAST(CONTEXT_INFO() AS varchar(128)) COLLATE Latin1_General_100_BIN , 
     0x00, 
     '') 
+1

Działa to jednak musiałem zmienić sortowanie do SQL_Latin1_General_CP437_BIN. Zostało to oparte na próbach i błędach, które nie pozostawiają mnie z dużą pewnością. Jak mogę wyjaśnić, które sortowanie powinienem używać? –

+0

@Poz - W swoim pytaniu nie podano wersji programu SQL Server. Jeśli poprzednio 2008 r., Sortowanie "100" nie będzie dostępne. –

+0

Przeprosiny. Pracuję w 2005 roku, jednak musi być odpowiedni dla wszystkich powyższych wersji. –

3

Robi dopełniane CHAR(0). Spróbuj:

set @temp_userCode = REPLACE(@temp_userCode COLLATE Latin1_General_BIN, CHAR(0), ''); 

(EDIT: dodano wyraźne COLLATE klauzulę, chociaż teraz czuję jakbym okradał Martin.)

+0

+1 Używam jawnej klauzuli cast i collate w mojej odpowiedzi [z powodu tego problemu] (https://connect.microsoft.com/SQLServer/feedback/details/708179/indefinite-hang-with-replace-statement-on -varbinary-max), ale pojawił się tylko w 'varbinary (max)'. –

+0

To rozwiązanie nie działa dla mnie, długość nadal wynosi 50. Może z powodu SQL 2005? –

+0

Właściwie znalazłem dwa - jeden działający 9.00.3042, drugi 9.00.4211 i działał - obie długości pokazują 8. –

0

Wymień losowo zawieść na różnych instalacji serwera SQL unless you specify the collation:

REPLACE(CAST(CONTEXT_INFO() AS varchar(128)) COLLATE Latin1_General_100_BIN , 0x00, '') 

serwera SQL ma dwa różne zachowania, w zależności od tego, jak jest on zainstalowany:

  • Wymiana jest pomyślna, gdy używane jest sortowanie SQL.
  • Wymiana nie powiedzie się, gdy jest używane sortowanie w systemie Windows.

Takie zachowanie został przedłożony Microsoft prawie ponad 7 lat temu:

Q: Po wypróbowaniu zastąpić NUL charakter z replace(), to działa to wartość ma SQL sortowanie, ale nie sortowanie Windows.

A: Wynika to z faktu, że 0x0000 jest niezdefiniowany znaków w systemie Windows sortowania. Wszystkie niezdefiniowane znaki są ignorowane podczas porównywania, sortowania, i dopasowywania wzorców. Dlatego szukanie "a" + char (0) naprawdę szuka "a", a wyszukiwanie znaku char (0) jest równoważne pustemu ciągowi znaków.

Sposób obsłużyć nieokreśloną postać jest nieco mylące, ale jest to sposób, że Windows zdefiniowane do nich sortować i SQL Server jest zgodny z ogólnym API Windows.

W zestawie SQL nie ma niezdefiniowanego znaku . Każdy kod punkt ma przypisaną wagę, dlatego nie widzimy tam problemu.

2

Spróbuj tego, że pracuje dla mnie na SQL Server 2005:

select cast(substring(CONTEXT_INFO(), 1, charindex(0x00, CONTEXT_INFO())-1) as varchar(128)); 

Brak niechlujny sortowania rozważyć :-)