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.


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)

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


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.


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.


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')

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

@ 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

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

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

2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0

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')

1

Najprostsze jest zawsze najlepsze:

Select EmployeeID*1 as EmployeeID 

-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`
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.