Formatowanie liczb przez wypełnienie początkowymi zerami w programie SQL Server

119

Mamy starą tabelę SQL, która była używana przez SQL Server 2000 przez blisko 10 lat.

W nim przechowywane są numery naszych identyfikatorów pracowników char(6)od 000001do 999999.

Piszę teraz aplikację internetową i muszę przechowywać numery identyfikatorów pracowników.

W mojej nowej tabeli mógłbym skorzystać ze skrótu i ​​skopiować starą tabelę, ale mam nadzieję na lepszy transfer danych, mniejszy rozmiar itp., Po prostu przechowując intwartości od 1do 999999.

W C # mogę szybko sformatować intwartość numeru odznaki przy użyciu

public static string GetBadgeString(int badgeNum) {
  return string.Format("{0:000000}", badgeNum);
  // alternate
  // return string.Format("{0:d6}", badgeNum);
}

Jak zmodyfikować to proste zapytanie SQL, aby również sformatować zwracaną wartość?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Jeśli EmployeeIDwynosi 7135, to zapytanie powinno zwrócić 007135.

jp2code
źródło
Skoro wiodące 0s są znaczące w tej dziedzinie, po co INTw ogóle zmieniać ją na?
Oded
2
SQL Server 2012 wreszcie będzie miał FORMATfunkcję taką jak C # :-)
marc_s
1
@Oden: intWartości zajmują znacznie mniej miejsca niż te char(6)i będzie ich wiele na wyprodukowaną część. Wydajność.
jp2code
Czy optymalizujesz, zanim napotkasz problem?
Oded
4
Zobaczmy, masz do miliona numerów odznak i myślisz, że możesz zapisać (według DATALENGTH()) dwa bajty każdy. Ponieważ kolumna może znajdować się w indeksie, możesz zaoszczędzić więcej niż 2 MB. Po dodaniu innych kolumn te 2 bajty mogą wystarczyć, aby zmniejszyć długość wiersza na tyle, aby zapisać stronę 4KB na wiersz. Czy to będzie hostowane na platformie mobilnej, czy może skupiasz się na nieproduktywnym obszarze?
HABO

Odpowiedzi:

172

Zmień liczbę 6 na dowolną wymaganą całkowitą długość:

SELECT REPLICATE('0',6-LEN(EmployeeId)) + EmployeeId

Jeśli kolumna to INT, możesz użyć RTRIM, aby niejawnie przekonwertować ją na VARCHAR

SELECT REPLICATE('0',6-LEN(RTRIM(EmployeeId))) + RTRIM(EmployeeId)

I kod do usunięcia tych zer i odzyskania „prawdziwej” liczby:

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)
Vince Pergolizzi
źródło
1
+1 Pokazałeś mi nawet, jak usunąć zera! Przetestuję to i zaznaczę to jako odpowiedź.
jp2code
nie potrzebujesz kodu, aby usunąć zera, po prostu przypisz lub przekonwertuj na int, a zostaną one automatycznie usunięte.
Jimbo
2
Działa to tylko wtedy, gdy przekazana wartość jest ciągiem znaków, jeśli przekażesz liczbę całkowitą, otrzymasz tę samą wartość, którą przekazałeś.
Mordy,
2
Chociaż jego stare… użycie „+ convert (varchar, EmployeeID)” zamiast „+ EmployeeID” powinno rozwiązać problem int
Krishna Sarma
3
jest to dobry sposób, chyba że EmployeeId jest większy niż 6 cyfr, co powoduje wynik NULL. Funkcja kontaktu jest odpowiedzią: SELECT CONCAT (REPLICATE ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Mahmoud Moravej
125

Po prostu użyj funkcji FORMAT (działa na SQL Server 2012 lub nowszym):

SELECT FORMAT(EmployeeID, '000000')
FROM dbo.RequestItems
WHERE ID=0 

Źródła: http://msdn.microsoft.com/en-us/library/hh213505.aspx

EdMorte
źródło
1
To stare pytanie - zanim pojawił się SQL Server 2012.
jp2code
19
Mimo to chciałbym teraz zobaczyć tę bańkę trochę bliżej szczytu.
Dave Haynes
4
Na wypadek gdyby ktoś się zastanawiał. Formatnie zachowuje typu danych, ale niejawnie konwertuje do nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph
2
W ten sposób jest to najprostsze i najlepsze rozwiązanie IMHO.
Robert Lujo
Pamiętaj o tej funkcji, jeśli używasz jej do dużych zbiorów danych
amd
33

W ten sposób możesz zmienić swoją procedurę

SELECT Right('000000' + CONVERT(NVARCHAR, EmployeeID), 6) AS EmpIDText, 
       EmployeeID
FROM dbo.RequestItems 
WHERE ID=0 

Jednak zakłada się, że twoja EmployeeIDjest wartością liczbową i ten kod zmienia wynik na ciąg, sugeruję ponowne dodanie oryginalnej wartości liczbowej

EDYCJA Oczywiście nie przeczytałem dokładnie powyższego pytania. Mówi, że pole jest char(6)więc EmployeeID nie jest wartością liczbową. Chociaż ta odpowiedź ma wartość samą w sobie, nie jest to poprawna odpowiedź na powyższe pytanie.

Steve
źródło
Myślę, że to najczystszy sposób na zrobienie tego. Dzięki
iheartcsharp
Czy to '000000'naprawdę konieczne…? '0'również działa dobrze. Czy bezpiecznie jest używać tylko jednego 0 ..?
shashwat
1
W rezultacie OP poprosił o łańcuch o długości 6 znaków. W szczególności, jeśli EmployeeID to 7135, to zapytanie powinno zwrócić 007135 . Użycie tylko jednego „0” 07135nie zwraca 007135. Cały pomysł polega na konkatenacji do ciągu 6-znakowego złożonego z całego 0łańcucha przekształconego EmployeedID, a następnie POCZĄTKUJĄC od prawej krawędzi weź 6 znaków. Niezależnie od długości ID, powyższa metoda zwraca zawsze ciąg zawierający tylko liczbę znaków zerowych wymaganą do osiągnięcia długości 6 znaków
Steve
Może to być 5 zer, '00000'ponieważ EmployeeIDbędzie zawierał co najmniej jedną cyfrę. Ale REPLICATE()funkcja wydaje się bardziej dopasowana, podobnie jak w innych odpowiedziach
nosklo
26

Nienawidziłem konieczności KONWERSJI int, a to wydaje się znacznie prostsze. Może nawet działać lepiej, ponieważ istnieje tylko jedna konwersja ciągów i proste dodawanie.

wybierz PRAWO (1000000 + EmployeeId, 6) ...

Tylko upewnij się, że wartość „1000000” ma co najmniej tyle zer, ile potrzeba.

JeffSahol
źródło
11

Piszę wszystko w jednym miejscu, wszystko działa u mnie dopinanie z 4 wiodącymi zerami :)

declare @number int =  1;
print right('0000' + cast(@number as varchar(4)) , 4)
print right('0000' + convert(varchar(4), @number) , 4)
print right(replicate('0',4) + convert(varchar(4), @number) , 4)
print  cast(replace(str(@number,4),' ','0')as char(4))
print format(@number,'0000')
Raj kumar
źródło
Obejmuje wszystkie potrzebne opcje. Dziękuję Ci.
kyurthich
6

Inny sposób, tylko dla kompletności.

DECLARE @empNumber INT = 7123
SELECT STUFF('000000', 6-LEN(@empNumber)+1, LEN(@empNumber), @empNumber)

Lub, zgodnie z zapytaniem

SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
         AS EmployeeCode
FROM dbo.RequestItems
WHERE ID=0
Jamiec
źródło
@ jp2code - musisz przeczytać, czym jest StackOverflow - jest edytowany wspólnie jak wiki - to nie jest twoje pytanie, gdy tylko je opublikujesz! Rzeczy, które są zwykle usuwane, to nadmierne „bzdury”, takie jak wcześniejsze podziękowanie i słaba gramatyka / kapitalizacja.
Jamiec
5

Od wersji 2012 i nowszych można używać

SELECT FORMAT(EmployeeID,'000000')
FROM dbo.RequestItems
WHERE ID=0
Hagop Simonian
źródło
4

Tak czysty, jak to tylko możliwe i daje możliwość zamiany na zmienne:

Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
WHERE ID=0
Divanshu
źródło
Jeśli EmployeeIDkolumna jest zdefiniowana jako, intto operator + będzie traktowany jako dodawanie, a nie konkatenacja, a więc zera zostaną utracone. Użycie convertpozwoli uniknąć tego problemu.
Wywołanie REPLICATE ('0', 6), aby uniknąć wpisywania '000000', jest po prostu marnotrawstwem ;-)
Mladen Mihajlovic
3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0
Jimbo
źródło
2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0
user1227804
źródło
Ups. Właściwie to dało mi to, 7135.0kiedy to dałem 7135.
jp2code
1

Rozwiązanie działa dla liczb ze znakiem / ujemnymi z wiodącymi zerami, dla wszystkich wersji Sql:

DECLARE
    @n money = -3,
    @length tinyint = 15,
    @decimals tinyint = 0

SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')
Zsolt v
źródło
1

Najprostsze jest zawsze najlepsze:

Select EmployeeID*1 as EmployeeID 
Michał
źródło
-1

W mojej wersji SQL nie mogę użyć REPLICATE. Więc zrobiłem to:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
Zlato010
źródło