Làm cách nào để bảo toàn các số 0 đứng đầu khi tôi chèn một số vào bảng này? [đóng cửa]


10

Tôi đã chèn hai bản ghi vào một bảng.

create table num(id int)
insert into num values(0023)
insert into num values(23)
select * from num

Khi tôi truy vấn chúng, tất cả chúng đều hiển thị dưới dạng 23. Điều đó có nghĩa là SQL Server bỏ qua các số 0 hàng đầu. Cơ chế đằng sau đó là gì? Làm cách nào để SQL Server trả về các giá trị khi tôi chèn chúng (tức là 002323)?


2
Tại sao bạn quan tâm đến các số không hàng đầu? Nếu chúng có ý nghĩa đối với hệ thống của bạn, thì idnên là loại VARCHARhoặc tương tự.
Nick Chammas

Chính xác thì làm thế nào để bạn mong đợi 0023 được mã hóa trong cơ sở dữ liệu như một cái gì đó khác với 23 hoặc 023 hoặc 0000000023? Tất cả đều đại diện cho cùng một số. Và int là kiểu dữ liệu SỐ. Không có chỗ cho máy chủ lưu trữ giá trị "số thập phân hàng đầu" này.
ErikE

Đây là một câu hỏi kém, và sẽ được đề cập trong bất kỳ giới thiệu nào về lớp lập trình. Một int không bao giờ có thể lưu trữ các số không hàng đầu, vì bản chất của ints. Điều này có thể được giải quyết bằng cách xem xét bất kỳ số lượng tài nguyên web. Điều này không cần đầu vào của một quản trị viên cơ sở dữ liệu.
jcolebrand

1
Số không hàng đầu được ngụ ý. Bên cạnh việc sử dụng một chuỗi thay vào đó, nếu bạn cần một số lượng cụ thể hàng đầu, đó là thông tin bổ sung ngoài những gì được lưu trữ trong một cột int. Một tùy chọn đang sử dụng cột chuỗi, nhưng một tùy chọn khác đang lưu trữ số lượng số 0 đứng đầu trong một cột khác hoặc trong giao diện người dùng. ví dụ, nếu UI luôn định dạng thành 4 chữ số với các số 0 đứng đầu, thì bạn đã lưu thông tin này trong UI. Nếu bạn cần số # 0 thay đổi và được lưu giữ cho mỗi bản ghi, bạn có thể lưu trữ thông tin đó trong một trường riêng thay thế.
Dave Cousineau

Câu trả lời:


27

0023không phải là một con số Đó là một chuỗi. 23là số SQL Server có thể nhận ra rằng các số 0 bổ sung đó là không cần thiết để xác định số, vì vậy nó bỏ qua chúng. Nếu bạn muốn phân phối một giá trị là 0023 cho ứng dụng, tôi khuyên bạn nên thực hiện định dạng ở phía ứng dụng. Theo cách đó, số được lưu trữ trong SQL Server vẫn là một số nếu bạn muốn thực hiện phép cộng, tổng hợp hoặc các phép tính khác. Nếu bạn thực sự phải lưu trữ dưới dạng ' 0023', bạn cần chuyển đổi nó thành trường ký tự; char, varar, nvarchar, nchar.


Nếu 0023 là chuỗi, làm thế nào tôi có thể chèn giá trị vào bảng mà tôi đã xác định id là định dạng int?
dùng8365

@ user8365 - Hoặc xác định idVARCHARhoặc chỉ chèn 23 thay vì 0023
Lamak

5
@ user8365 - Bạn đang hỏi liệu bạn có thể khiến SQL Server vi phạm tính toàn vẹn miền của trường đó không. Bạn không thể. Nếu 0023là một chuỗi thì lưu trữ nó dưới dạng một chuỗi. Nếu không, hãy lưu nó dưới dạng INT và quên đi các số 0 đứng đầu.
Nick Chammas

Chính xác những gì @NickChammas đã nói. Bạn không có lựa chọn nào ở đây. 23 là một số, 0023 là một chuỗi. Nếu bạn muốn một số, coi nó như một số. Giống như câu trả lời của tôi nói, nếu nó cần sắp xếp như một số, cộng, trừ, nhân, chia, v.v., giống như một số, thì nó cần phải là một số. Không có lựa chọn. Không có đối số. Số không hàng đầu chỉ là định dạng. Làm điều đó trong mã ứng dụng hoặc một nơi nào đó.
Cấp Fritchey

@Grant Tôi không thể đồng ý rằng các số 0 đứng đầu chỉ là định dạng. Chúng là hợp pháp trong bất kỳ hệ thống số; tuy nhiên, 0023b10 = 23b10; vì vậy, bất kỳ hệ thống lưu trữ nào cũng đạt được mức độ nén bằng cách không mã hóa tất cả các số 0 hàng đầu. Vì vậy, về cơ bản người hỏi của chúng tôi đang hỏi sai câu hỏi. Tại sao 0023 không phải là số nguyên? Nó là một số nguyên! Chúng ta không cần phải mã hóa vô số các chữ số hàng đầu để thể hiện nó như vậy.
ooutwire

5

Nó đã được nói trong các câu trả lời khác đó 00023là một con số; Tôi chỉ muốn thêm rằng bạn có thể sử dụng các cột được tính toán để hiển thị số đó bằng định dạng tùy chỉnh. Ví dụ,

create table num_table(id int not null primary key identity(1,1),
num int, leading_zeros smallint,
constraint chk_leading_zero_nonnegative check (leading_zero>=0),
num_formatted as replicate('0',coalesce(leading_zeros,0)) +cast(num as varchar(10)));
insert into num_table(num,leading_zeros) values(23,2) ;
select num_formatted from num_table; -- output '0023'

Điểm tốt, hoàn toàn đáng chú ý.
Cấp Fritchey

0

0023 là một số nhưng các kiểu dữ liệu int và số khác không lưu trữ các số 0 đứng đầu vì không có lý do toán học nào để làm như vậy.

Nếu bạn cần lưu trữ các số 0 hàng đầu, hãy sử dụng kiểu dữ liệu chuỗi như, char, varchar, v.v.


1
Nếu chúng ta giả sử rằng đó INTlà độ dài cố định (như 32 bit) và ký hiệu nhị phân được sử dụng để lưu trữ chúng, thì các số 0 đứng đầu thực sự được lưu trữ. Nhưng chúng không được hiển thị trong đầu ra.
ypercubeᵀᴹ

@ypercube - Đúng, nhưng số lượng số 0 đứng đầu chỉ đơn giản là những gì được yêu cầu để điền vào 32 bit (trái ngược với định nghĩa của người dùng).
Nick Chammas

@Nick: Vâng, không có tranh luận ở đó. Tôi nghĩ rằng điểm KHÔNG phải là có hay không các số 0 đứng đầu được lưu trữ. Đó là liệu hai phiên bản của cùng một số có thể được lưu trữ trong kiểu dữ liệu, một có và một không có số 0 đứng đầu.
ypercubeᵀᴹ

Nhưng điều này không có ý nghĩa. Hai số 0 đứng đầu thập phân hoàn toàn không liên quan đến số lượng số 0 đứng đầu trong số nguyên 32 bit. Hãy xem xét số thập phân 15- chỉ mất một chữ số trong hệ thập lục phân , F. Họ đã có một số "số 0 hàng đầu" khác nhau. 2147483647 là 10 chữ số, nhưng trong hex chỉ có 7FFFFFFF hoặc 8 chữ số.
ErikE

Về cơ bản, người ta phải xem xét hệ thống số toán học mà chúng ta đang sử dụng ... trong trường hợp này là số thập phân (cơ sở 10). 23 là số thập phân; nó là 0x1000 + 0x100 + 2x10 + 3 = 23. Trong bát phân, nó là 2X8 + 3, v.v. Vì vậy, để nói với công cụ lưu trữ, "lưu trữ 23 với hai số 0 đứng đầu" không hữu ích, vì nó chỉ mã hóa cùng một kết quả cuối cùng, đó là 23. Máy chủ SQL không bỏ qua các số 0 của bạn, nó chỉ trả về cho bạn một giá trị thập phân bằng với số mà bạn đã chèn, tức là 0023 hoặc 23.
ooutwire 17/03/2016
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.