Inne odpowiedzi tutaj, aby nie brać pod uwagę, jeśli masz wszystkie zero (lub nawet jedno zero).
Niektórzy zawsze domyślnie ustawiają pusty ciąg na zero, co jest błędne, gdy ma pozostać puste.
Przeczytaj ponownie oryginalne pytanie. To odpowiada na to, czego chce Pytający.
Rozwiązanie nr 1:
--This example uses both Leading and Trailing zero's.
--Avoid losing those Trailing zero's and converting embedded spaces into more zeros.
--I added a non-whitespace character ("_") to retain trailing zero's after calling Replace().
--Simply remove the RTrim() function call if you want to preserve trailing spaces.
--If you treat zero's and empty-strings as the same thing for your application,
-- then you may skip the Case-Statement entirely and just use CN.CleanNumber .
DECLARE @WackadooNumber VarChar(50) = ' 0 0123ABC D0 '--'000'--
SELECT WN.WackadooNumber, CN.CleanNumber,
(CASE WHEN WN.WackadooNumber LIKE '%0%' AND CN.CleanNumber = '' THEN '0' ELSE CN.CleanNumber END)[AllowZero]
FROM (SELECT @WackadooNumber[WackadooNumber]) AS WN
OUTER APPLY (SELECT RTRIM(RIGHT(WN.WackadooNumber, LEN(LTRIM(REPLACE(WN.WackadooNumber + '_', '0', ' '))) - 1))[CleanNumber]) AS CN
--Result: "123ABC D0"
Rozwiązanie nr 2 (z przykładowymi danymi):
SELECT O.Type, O.Value, Parsed.Value[WrongValue],
(CASE WHEN CHARINDEX('0', T.Value) > 0--If there's at least one zero.
AND LEN(Parsed.Value) = 0--And the trimmed length is zero.
THEN '0' ELSE Parsed.Value END)[FinalValue],
(CASE WHEN CHARINDEX('0', T.Value) > 0--If there's at least one zero.
AND LEN(Parsed.TrimmedValue) = 0--And the trimmed length is zero.
THEN '0' ELSE LTRIM(RTRIM(Parsed.TrimmedValue)) END)[FinalTrimmedValue]
FROM
(
VALUES ('Null', NULL), ('EmptyString', ''),
('Zero', '0'), ('Zero', '0000'), ('Zero', '000.000'),
('Spaces', ' 0 A B C '), ('Number', '000123'),
('AlphaNum', '000ABC123'), ('NoZero', 'NoZerosHere')
) AS O(Type, Value)--O is for Original.
CROSS APPLY
( --This Step is Optional. Use if you also want to remove leading spaces.
SELECT LTRIM(RTRIM(O.Value))[Value]
) AS T--T is for Trimmed.
CROSS APPLY
( --From @CadeRoux's Post.
SELECT SUBSTRING(O.Value, PATINDEX('%[^0]%', O.Value + '.'), LEN(O.Value))[Value],
SUBSTRING(T.Value, PATINDEX('%[^0]%', T.Value + '.'), LEN(T.Value))[TrimmedValue]
) AS Parsed
Wyniki:
Podsumowanie:
Możesz użyć tego, co mam powyżej, do jednorazowego usunięcia wiodących zer.
Jeśli planujesz często go używać, umieść go w funkcji Inline-Table-Valued (ITVF).
Twoje obawy dotyczące problemów z wydajnością UDF są zrozumiałe.
Jednak ten problem dotyczy tylko funkcji All-Scalar i Multi-Statement-Table Functions.
Używanie ITVF jest w porządku.
Mam ten sam problem z naszą bazą danych innej firmy.
W przypadku pól alfanumerycznych wielu jest wprowadzanych bez wiodących spacji, do cholery!
To sprawia, że łączenie jest niemożliwe bez usunięcia brakujących zer wiodących.
Wniosek:
Zamiast usuwać zera wiodące, możesz rozważyć po prostu uzupełnienie przyciętych wartości zerami wiodącymi podczas łączenia.
Jeszcze lepiej, wyczyść dane w tabeli, dodając wiodące zera, a następnie odbuduj indeksy.
Myślę, że byłoby to DUŻO szybsze i mniej złożone.
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF(' 0A10 ', ''))), 10)--0000000A10
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF('', ''))), 10)--NULL --When Blank.