Memformat Angka dengan mengisi dengan angka nol di depan di SQL Server


119

Kami memiliki tabel SQL lama yang digunakan oleh SQL Server 2000 selama hampir 10 tahun.

Di dalamnya, nomor lencana karyawan kami disimpan mulai char(6)dari 000001hingga 999999.

Saya sedang menulis aplikasi web sekarang, dan saya perlu menyimpan nomor lencana karyawan.

Di tabel baru saya, saya dapat mengambil jalan pintas dan menyalin tabel lama, tetapi saya berharap transfer data yang lebih baik, ukuran yang lebih kecil, dll, hanya dengan menyimpan intnilai from 1to 999999.

Di C #, saya dapat dengan cepat memformat intnilai untuk nomor lencana menggunakan

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

Bagaimana cara mengubah kueri SQL sederhana ini untuk memformat nilai yang dikembalikan juga?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Jika EmployeeID7135, kueri ini harus kembali 007135.


Sejak memimpin 0sangat penting untuk bidang ini, mengapa mengubahnya INTsama sekali?
Oded

2
SQL Server 2012 akhirnya akan memiliki FORMATfungsi seperti C # :-)
marc_s

1
@Oden: intNilai - nilai memakan ruang yang jauh lebih sedikit char(6), dan akan ada beberapa entri ini per bagian yang diproduksi. Efisiensi.
jp2code

Apakah Anda mengoptimalkan sebelum mengalami masalah?
Oded

4
Mari kita lihat, Anda memiliki hingga satu juta nomor lencana dan Anda membayangkan bahwa Anda dapat menyimpan (menurut DATALENGTH()) masing-masing dua byte. Karena kolom mungkin dalam indeks, Anda bisa menghemat lebih dari 2MB. Dan dengan kolom lain ditambahkan, 2 byte itu mungkin cukup untuk mengurangi panjang baris yang cukup untuk menyimpan halaman 4KB per baris. Apakah ini akan dihosting di platform seluler, atau mungkinkah Anda memfokuskan perhatian Anda di area yang tidak produktif?
HABO

Jawaban:


172

Ubah angka 6 menjadi berapa pun panjang total Anda:

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

Jika kolomnya INT, Anda dapat menggunakan RTRIM untuk mengubahnya secara implisit menjadi VARCHAR

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

Dan kode untuk menghapus 0 ini dan mendapatkan kembali nomor 'asli':

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

1
+1 Anda bahkan menunjukkan kepada saya cara menghapus 0! Izinkan saya menguji ini, dan saya akan menandainya sebagai jawaban.
jp2code

Anda tidak perlu kode untuk menghapus nol, cukup tetapkan atau ubah menjadi int dan mereka akan dihapus secara otomatis.
Jimbo

2
Ini hanya berfungsi jika nilai yang diteruskan adalah string, jika Anda meneruskan integer Anda mendapatkan nilai yang sama dengan yang Anda berikan.
Mordy

2
Meskipun lama ... menggunakan "+ convert (varchar, EmployeeID)" alih-alih "+ EmployeeID" seharusnya menyelesaikan masalah int
Krishna Sarma

3
ini adalah cara yang baik kecuali jika EmployeeId lebih besar dari 6 digit yang menyebabkan hasil NULL. Fungsi kontak adalah jawabannya: SELECT CONCAT (REPLICATE ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Mahmoud Moravej

125

Cukup gunakan fungsi FORMAT (berfungsi di SQL Server 2012 atau yang lebih baru):

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

Referensi: http://msdn.microsoft.com/en-us/library/hh213505.aspx


1
Ini adalah pertanyaan lama - sebelum SQL Server 2012 keluar.
jp2code

19
Namun, saya ingin melihat gelembung ini lebih dekat ke atas sekarang.
Dave Haynes

4
Untuk berjaga-jaga jika ada yang bertanya-tanya. Formattidak mempertahankan tipe data tetapi secara implisit mengonversi ke nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph

2
Cara ini adalah yang paling sederhana dan IMHO adalah solusi terbaik.
Robert Lujo

Perhatikan fungsi ini jika Anda menggunakannya untuk kumpulan data besar
amd

33

Anda dapat mengubah prosedur Anda dengan cara ini

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

Namun ini mengasumsikan bahwa Anda EmployeeIDadalah nilai numerik dan kode ini mengubah hasilnya menjadi string, saya sarankan untuk menambahkan lagi nilai numerik asli

EDIT Tentu saja saya belum membaca dengan seksama pertanyaan di atas. Dikatakan bahwa bidang tersebut adalah char(6)EmployeeID bukan nilai numerik. Meskipun jawaban ini masih memiliki nilai, itu bukanlah jawaban yang benar untuk pertanyaan di atas.


Ini adalah cara terbersih untuk melakukannya menurut saya. Terima kasih
iheartcsharp

Apakah itu '000000'benar-benar perlu ..? '0'juga bekerja dengan baik. Apakah aman menggunakan hanya satu 0 ..?
shashwat

1
OP meminta string sepanjang 6 karakter sebagai hasilnya. Khususnya jika EmployeeID adalah 7135, kueri ini harus menghasilkan 007135 . Menggunakan hanya satu '0' 07135tidak akan menghasilkan hasil 007135. Seluruh ide adalah untuk menggabungkan ke string 6 karakter yang terdiri dari semua 0string yang dikonversi EmployeedID, kemudian MULAI dari tepi kanan ambil 6 karakter. Berapa pun panjang ID adalah metode di atas selalu mengembalikan string dengan hanya jumlah nol karakter yang diperlukan untuk mencapai panjang 6 karakter
Steve

Bisa jadi 5 angka nol '00000'karena surat EmployeeIDwasiat berisi setidaknya satu digit. Tetapi REPLICATE()fungsinya tampaknya lebih cocok, seperti di jawaban lain
nosklo

26

Benci harus MENGUBAH int, dan ini tampaknya jauh lebih sederhana. Bahkan dapat berkinerja lebih baik karena hanya ada satu konversi string dan penambahan sederhana.

pilih KANAN (1000000 + EmployeeId, 6) ...

Pastikan saja "1000000" memiliki setidaknya nol sebanyak ukuran yang dibutuhkan.


11

Saya memposting semua di satu tempat, semua bekerja untuk saya pad dengan 4 nol di depan :)

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

Ini mencakup semua opsi yang diperlukan. Terima kasih.
kyurthich

6

Cara lain, hanya untuk kelengkapan.

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

Atau, sesuai permintaan Anda

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

@ jp2code - Anda perlu membaca tentang apa itu StackOverflow - diedit secara kolaboratif seperti wiki - ini bukan pertanyaan Anda segera setelah Anda mempostingnya! Hal-hal yang biasanya diedit adalah "halus" yang berlebihan seperti ucapan terima kasih sebelumnya dan tata bahasa / kapitalisasi yang buruk.
Jamiec

5

Mulai versi 2012 dan seterusnya, Anda dapat menggunakan

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

4

Sebersih mungkin dan berikan ruang lingkup penggantian dengan variabel:

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

Jika EmployeeIDkolom didefinisikan sebagai intmaka operator + akan diperlakukan sebagai penjumlahan daripada penggabungan sehingga angka nol akan hilang. Menggunakan convertakan menghindari masalah ini.

Memanggil REPLICATE ('0', 6) untuk menghindari mengetik '000000' hanya sia-sia ;-)
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. Sebenarnya, ini memberi saya 7135.0saat saya memberikannya 7135.
jp2code

1

Solusi ini berfungsi untuk bilangan bertanda / negatif dengan nol di depan, untuk semua versi Sql:

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

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

1

Yang paling sederhana selalu yang terbaik:

Select EmployeeID*1 as EmployeeID 

-1

Dalam versi SQL saya, saya tidak dapat menggunakan REPLICATE. JADI saya melakukan ini:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.