Định dạng số bằng cách đệm với các số không ở đầu trong SQL Server


119

Chúng tôi có một bảng SQL cũ đã được sử dụng bởi SQL Server 2000 trong gần 10 năm.

Trong đó, số huy hiệu nhân viên của chúng tôi được lưu trữ như char(6)từ 000001đến 999999.

Tôi hiện đang viết một ứng dụng web và tôi cần lưu trữ số huy hiệu của nhân viên.

Trong bảng mới của tôi, tôi có thể cắt ngắn và sao chép bảng cũ, nhưng tôi hy vọng truyền dữ liệu tốt hơn, kích thước nhỏ hơn, v.v. bằng cách lưu trữ các intgiá trị từ 1đến 999999.

Trong C #, tôi có thể nhanh chóng định dạng một intgiá trị cho số huy hiệu bằng cách sử dụng

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

Làm cách nào để sửa đổi truy vấn SQL đơn giản này để định dạng cả giá trị trả về?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Nếu EmployeeIDlà 7135, truy vấn này sẽ trả về 007135.


0các s đứng đầu rất quan trọng đối với trường này, tại sao lại thay đổi nó thành một INT?
Oded

2
SQL Server 2012 cuối cùng sẽ có một FORMATchức năng như C # :-)
marc_s

1
@Oden: Các intgiá trị chiếm ít không gian hơn đáng kể char(6)và sẽ có nhiều mục nhập này trên mỗi phần được sản xuất. Hiệu quả.
jp2code

Bạn có đang tối ưu hóa trước khi gặp sự cố không?
Oded

4
Hãy xem, bạn có tới một triệu số huy hiệu và bạn tính rằng bạn có thể tiết kiệm (theo DATALENGTH()) hai byte mỗi số. Vì cột có thể nằm trong chỉ mục, bạn có thể tiết kiệm hơn 2MB. Và với các cột khác được thêm vào, 2 byte đó có thể vừa đủ để giảm độ dài của một hàng đủ để lưu một trang 4KB trên mỗi hàng. Điều này sẽ được lưu trữ trên nền tảng di động hay bạn có thể đang tập trung sự chú ý của mình vào một lĩnh vực không hiệu quả?
HABO

Câu trả lời:


172

Thay đổi số 6 thành bất kỳ tổng chiều dài của bạn cần là:

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

Nếu cột là INT, bạn có thể sử dụng RTRIM để chuyển đổi hoàn toàn nó thành VARCHAR

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

Và mã để loại bỏ những số 0 này và lấy lại số 'thực':

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)

1
+1 Bạn thậm chí đã chỉ cho tôi cách xóa các số 0! Hãy để tôi kiểm tra điều này, và tôi sẽ đánh dấu nó như một câu trả lời.
jp2code

bạn không cần mã để xóa các số 0, chỉ cần gán hoặc chuyển đổi thành int và chúng sẽ tự động bị xóa.
Jimbo

2
Điều này chỉ hoạt động nếu giá trị được truyền vào là một chuỗi, nếu bạn chuyển một số nguyên, bạn sẽ nhận được cùng một giá trị mà bạn đã chuyển vào.
Mordy

2
Mặc dù cũ ... sử dụng "+ convert (varchar, EmployeeID)" thay vì "+ EmployeeID" sẽ giải quyết được vấn đề int
Krishna Sarma

3
đó là một cách tốt trừ khi EmployeeId lớn hơn 6 chữ số gây ra kết quả NULL. Chức năng tiếp xúc là câu trả lời: SELECT CONCAT (tái tạo ( '0', 6-LEN (CONVERT (varchar, EmployeeID))), EmployeeID)
Mahmoud Moravej

125

Chỉ cần sử dụng hàm FORMAT (hoạt động trên SQL Server 2012 hoặc mới hơn):

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

Tham khảo: http://msdn.microsoft.com/en-us/library/hh213505.aspx


1
Đây là một câu hỏi cũ - trước khi SQL Server 2012 ra mắt.
jp2code

19
Tuy nhiên, tôi muốn nhìn thấy bong bóng này gần với đỉnh hơn một chút.
Dave Haynes

4
Đề phòng có ai thắc mắc. Formatkhông bảo toàn kiểu dữ liệu nhưng chuyển đổi ngầm thành nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph

2
Cách này là đơn giản nhất và IMHO là giải pháp tốt nhất.
Robert Lujo

Hãy lưu ý về chức năng này nếu bạn đang sử dụng nó cho tập dữ liệu lớn
amd

33

Bạn có thể thay đổi quy trình của mình theo cách này

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

Tuy nhiên, điều này giả định rằng của bạn EmployeeIDlà một giá trị số và mã này thay đổi kết quả thành một chuỗi, tôi khuyên bạn nên thêm lại giá trị số ban đầu

CHỈNH SỬA Tất nhiên tôi chưa đọc kỹ câu hỏi trên. Nó nói rằng trường là một char(6)nên EmployeeID không phải là một giá trị số. Mặc dù câu trả lời này vẫn có giá trị, nhưng nó không phải là câu trả lời chính xác cho câu hỏi trên.


Đây là cách làm sạch nhất mà tôi nghĩ. Cảm ơn
iheartcsharp 13/03

Điều đó có '000000'thực sự cần thiết không ..? '0'cũng hoạt động tốt. Có an toàn không khi chỉ sử dụng một số 0 ..?
shashwat

1
Kết quả là OP đã yêu cầu một chuỗi độ dài 6 ký tự. Cụ thể nếu EmployeeID là 7135, truy vấn này sẽ trả về 007135 . Chỉ sử dụng một '0' 07135không trả về 007135. Toàn bộ ý tưởng là nối với một chuỗi 6 ký tự bao gồm tất cả 0chuỗi EmployeedID được chuyển đổi, sau đó BẮT ĐẦU từ cạnh bên phải lấy 6 ký tự. Dù chiều dài ID là phương pháp trên lợi nhuận luôn luôn là một chuỗi với chỉ số zero char cần thiết để đạt được độ dài 6 char
Steve

Nó có thể là 5 số 0 '00000'vì di EmployeeIDchúc chứa ít nhất một chữ số. Tuy nhiên, REPLICATE()chức năng dường như phù hợp hơn, như trong câu trả lời khác
nosklo

26

Rất ghét phải CHUYỂN ĐỔI int, và điều này có vẻ đơn giản hơn nhiều. Thậm chí có thể hoạt động tốt hơn vì chỉ có một chuyển đổi chuỗi và bổ sung đơn giản.

chọn RIGHT (1000000 + EmployeeId, 6) ...

Chỉ cần đảm bảo "1000000" có ít nhất bao nhiêu số 0 theo kích thước cần thiết.


11

Tôi đang đăng tất cả ở một nơi, tất cả đều hoạt động để tôi có 4 số 0 ở đầu :)

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

Điều này bao gồm tất cả các tùy chọn cần thiết. Cảm ơn bạn.
kyurthich

6

Một cách khác, chỉ cho sự hoàn chỉnh.

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

Hoặc, theo truy vấn của bạn

SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
         AS EmployeeCode
FROM dbo.RequestItems
WHERE ID=0

@ jp2code - bạn cần phải đọc StackOverflow là gì - nó được biên tập cộng tác giống như một wiki - đó không phải là câu hỏi của bạn ngay sau khi bạn đăng nó! Những thứ thường bị chỉnh sửa quá mức như "cảm ơn" trước và ngữ pháp / viết hoa kém.
Jamiec

5

Từ phiên bản 2012 trở đi, bạn có thể sử dụng

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

4

Càng sạch càng tốt và cung cấp phạm vi thay thế bằng các biến:

Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
WHERE ID=0

Nếu EmployeeIDcột được xác định là intthì toán tử + sẽ được coi là phép cộng chứ không phải là nối và do đó các số không sẽ bị mất. Sử dụng convertsẽ tránh được vấn đề này.

Kêu gọi tái tạo ( '0', 6) để tránh gõ '000000' chỉ là lãng phí ;-)
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

Rất tiếc. Trên thực tế, điều này cho tôi 7135.0khi tôi cho nó 7135.
jp2code

1

Giải pháp hoạt động cho các số có dấu / âm với các số không ở đầu, cho tất cả các phiên bản Sql:

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

SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')

1

Đơn giản nhất luôn là tốt nhất:

Select EmployeeID*1 as EmployeeID 

-1

Trong phiên bản SQL của tôi, tôi không thể sử dụng REPLICATE. VẬY tôi đã làm điều này:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.