Pad string dengan nol terkemuka sehingga panjangnya 3 karakter di SQL Server 2008

398

Saya memiliki string yang panjangnya hingga 3 karakter saat pertama kali dibuat di SQL Server 2008 R2.

Saya ingin menambahkannya dengan angka nol di depan, jadi jika nilai aslinya adalah '1' maka nilai baru adalah '001'. Atau jika nilai aslinya adalah '23' nilai baru adalah '023'. Atau jika nilai aslinya adalah '124' maka nilai baru sama dengan nilai asli.

Saya menggunakan SQL Server 2008 R2. Bagaimana saya melakukan ini menggunakan T-SQL?

Sunil
sumber

Jawaban:

681

Jika bidang sudah menjadi string, ini akan berfungsi

 SELECT RIGHT('000'+ISNULL(field,''),3)

Jika Anda ingin nulls ditampilkan sebagai '000'

Mungkin bilangan bulat - maka Anda ingin

 SELECT RIGHT('000'+CAST(field AS VARCHAR(3)),3)

Seperti yang dipersyaratkan oleh pertanyaan, jawaban ini hanya berfungsi jika panjang <= 3, jika Anda menginginkan sesuatu yang lebih besar Anda perlu mengubah konstanta string dan dua konstanta bilangan bulat dengan lebar yang dibutuhkan. misalnya'0000' and VARCHAR(4)),4

Hogan
sumber
8
Saya memiliki bidang Char (6) yang memiliki beberapa nilai yang hanya 2-3 char panjang dan di atas tidak bekerja untuk saya. Saya harus menambahkan RTRIM di sekitar '000000' + ISNULL (FIELD, '') agar dapat berfungsi.
DWiener
3
Hogan ya saya dapat itu, tapi tidak peduli berapa lama string itu tidak bekerja, saya agak terlalu sibuk untuk mencari tahu mengapa tetapi intinya adalah bahwa dengan bidang CHAR (6) saya yang hanya melakukan KANAN ('000000 '+ ISNULL (bidang,' '), 6) tidak berfungsi tetapi KANAN (RTRIM (' 000000 '+ ISNULL (bidang,' ')), 6) berhasil.
DWiener
2
oh saya mengerti, Anda memiliki ruang di sebelah kanan nomor yang dikodekan sebagai string.
Hogan
3
@dwiener Anda mendapatkan perilaku ini karena char adalah tipe data panjang tetap, jadi dalam kasus Anda char (6) berarti 6 karakter. Jika nilai aktual Anda kurang dari 6 itu diisi dengan kosong di sebelah kanan sehingga jawaban yang diusulkan akan menghasilkan hasil yang cocok untuk char (6).
Giannis Paraskevopoulos
2
@Hogan, ya, tapi pertanyaan ini adalah hasil teratas google untuk "sql add leading nol", jadi saya pikir ini akan berguna bagi banyak orang (yang tidak menggunakan sqlserver, tetapi google pertanyaan ini) untuk mengetahui bahwa di database lain mungkin ada fungsi lpad yang lebih nyaman. Terima kasih.
diralik
142

Meskipun pertanyaannya adalah untuk SQL Server 2008 R2, jika seseorang membaca ini dengan versi 2012 dan di atasnya, sejak itu menjadi lebih mudah dengan menggunakan FORMAT .

Anda dapat meneruskan string format numerik standar atau string format numerik khusus sebagai argumen format (terima kasih kepada Vadim Ovchinnikov untuk petunjuk ini).

Untuk pertanyaan ini misalnya kode suka

DECLARE @myInt INT = 1;
-- One way using a standard numeric format string
PRINT FORMAT(@myInt,'D3');
-- Other way using a custom numeric format string
PRINT FORMAT(@myInt,'00#');

output

001
001
Gza
sumber
2
Apa yang terjadi jika nomor input adalah 111 atau 11?
Hogan
6
Untuk 1 adalah 001, untuk 11 adalah 011 dan untuk 111 adalah 111
Géza
2
Anda dapat menggunakan 'D3' alih-alih '00 # '.
Vadim Ovchinnikov
1
tampaknya jauh lebih lambat daripada jawaban yang diterima tetapi sooo jauh lebih mudah jika tidak bekerja dengan data dalam jumlah besar
root
2
Meskipun tampaknya tidak masuk akal, perlu dicatat bahwa FORMAT hanya bekerja dengan tipe numerik dan tanggal, bukan varchar.
strattonn
120

Metode aman:

SELECT REPLACE(STR(n,3),' ','0')

Ini memiliki keuntungan mengembalikan string '***'untuk n <0 atau n> 999, yang merupakan indikator input out-of-bounds yang bagus dan jelas. Metode lain yang tercantum di sini akan gagal secara diam-diam dengan memotong input ke substring 3 karakter.

Segera
sumber
10
Sial, siapa pun yang mendarat di halaman ini akan membantu mengapung ini ke atas!
MarioDS
1
Berhati-hatilah dengan metode ini. Ketika ekspresi melebihi panjang yang ditentukan, string mengembalikan ** untuk panjang yang ditentukan. untuk mis str (n, 10), ketika n = 1000000000 maka Anda akan memiliki bintang (*) muncul.
Tidak mengikat
Saya tidak tahu cara kerjanya tetapi luar biasa dan sederhana.
RaRdEvA
1
Hati-hati dengan ini, string memecahnya (dan OP meminta "padding a string"). Bekerja: SELECT REPLACE(STR('1',3),' ','0')Breaks: SELECT REPLACE(STR('1A',3),' ','0'). Ini baru saja membakar saya hari ini ketika seorang pengguna memasukkan surat ke dalam string masukan dan saya gagal menguji kasus itu.
Jeff Mergler
@Unggound Ini adalah bagaimana ini dimaksudkan untuk bekerja, poster sudah mengatakannya. Lebih baik mengembalikan *** daripada nilai terpotong seperti semua proposal lain lakukan, itu menunjukkan bahwa parameternya salah.
Marc Guillot
32

Berikut adalah teknik yang lebih umum untuk bantalan kiri dengan lebar yang diinginkan:

declare @x     int     = 123 -- value to be padded
declare @width int     = 25  -- desired width
declare @pad   char(1) = '0' -- pad character

select right_justified = replicate(
                           @pad ,
                           @width-len(convert(varchar(100),@x))
                           )
                       + convert(varchar(100),@x)

Namun, jika Anda berurusan dengan nilai-nilai negatif, dan menggunakan angka nol di depan, teknik ini atau teknik yang disarankan lainnya tidak akan berfungsi. Anda akan mendapatkan sesuatu yang terlihat seperti ini:

00-123

[Mungkin bukan yang Anda inginkan]

Jadi ... Anda harus melompati beberapa simpai tambahan Berikut ini satu pendekatan yang akan memformat angka negatif dengan benar:

declare @x     float   = -1.234
declare @width int     = 20
declare @pad   char(1) = '0'

select right_justified = stuff(
         convert(varchar(99),@x) ,                            -- source string (converted from numeric value)
         case when @x < 0 then 2 else 1 end ,                 -- insert position
         0 ,                                                  -- count of characters to remove from source string
         replicate(@pad,@width-len(convert(varchar(99),@x)) ) -- text to be inserted
         )

Orang harus mencatat bahwa convert()panggilan harus menentukan [n]varcharpanjang yang cukup untuk menahan hasil yang dikonversi dengan pemotongan.

Nicholas Carey
sumber
2
@StenPetrov, Terima kasih. Itu semua tergantung pada apa yang ingin Anda capai. Satu hal yang saya pelajari untuk bergantung pada basis data produksi dunia nyata yang besar adalah adanya data buruk dari satu jenis atau lainnya. Dan saya lebih suka menghindari panggilan telepon jam 3 pagi jika saya bisa; ^)
Nicholas Carey
:) masih ketika panggilan 3AM masuk saya lebih suka harus membaca 1 baris sederhana dari 10 yang kompleks. Menambahkan variabel lebih jauh memperburuk keadaan, terutama jika anggota tim lain memutuskan untuk menghitungnya dengan cepat dan tidak memeriksa @width non-negatif ...
Sten Petrov
Variabel-variabel yang ditambahkan hanya untuk generalisasi - Anda dapat mengkodekan nilainya dengan keras. Untuk liner satu, Anda dapat membuat fungsi skalar - maka Anda memiliki liner satu.
Gerard ONeill
30

Berikut adalah varian jawaban Hogan yang saya gunakan di SQL Server Express 2012:

SELECT RIGHT(CONCAT('000', field), 3)

Alih-alih khawatir jika bidangnya berupa string atau tidak, saya hanya CONCATmelakukannya, karena bagaimanapun juga akan menghasilkan string. Selain itu jika bidangnya bisa a NULL, menggunakan ISNULLmungkin diperlukan untuk menghindari fungsi mendapatkan NULLhasil.

SELECT RIGHT(CONCAT('000', ISNULL(field,'')), 3)
jahu
sumber
1
Sejauh yang saya ingat CONCAT hanya mengabaikan nilai jika itu nol jadi yang pertama berfungsi dengan baik.
Marie
Solusi ini akan bekerja terlepas dari len Field
Tidak
23

Saya selalu menemukan metode berikut ini sangat membantu.

REPLICATE('0', 5 - LEN(Job.Number)) + CAST(Job.Number AS varchar) as 'NumberFull'
Tagihan
sumber
15

Gunakan fungsi ini yang sesuai dengan setiap situasi.

CREATE FUNCTION dbo.fnNumPadLeft (@input INT, @pad tinyint)
RETURNS VARCHAR(250)
AS BEGIN
    DECLARE @NumStr VARCHAR(250)

    SET @NumStr = LTRIM(@input)

    IF(@pad > LEN(@NumStr))
        SET @NumStr = REPLICATE('0', @Pad - LEN(@NumStr)) + @NumStr;

    RETURN @NumStr;
END

Output sampel

SELECT [dbo].[fnNumPadLeft] (2016,10) -- returns 0000002016
SELECT [dbo].[fnNumPadLeft] (2016,5) -- returns 02016
SELECT [dbo].[fnNumPadLeft] (2016,2) -- returns 2016
SELECT [dbo].[fnNumPadLeft] (2016,0) -- returns 2016 
Salar
sumber
Ini harus menjadi jawaban yang diterima karena berfungsi pada angka dan string . Dan jika Anda tidak ingin menggunakan fungsi (tapi mengapa tidak) sesuatu seperti ini juga berfungsi: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;yang mengembalikan contoh pertama Salar di atas. Terima kasih, Salar.
Jeff Mergler
Komentar saya di atas mengandung kesalahan ketik, seharusnya berbunyi: DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;yang kembali 0000002016pada contoh pertama di atas.
Jeff Mergler
@ JeffMergler - bagaimana ini bekerja pada angka dan string? Ini adalah fungsi yang mengambil parameter integer. Pertanyaannya adalah tentang string.
Hogan
5

Bagi mereka yang ingin memperbarui data yang ada di sini adalah pertanyaan:

update SomeEventTable set eventTime=RIGHT('00000'+ISNULL(eventTime, ''),5)
Alan B. Dee
sumber
3

Untuk bilangan bulat, Anda dapat menggunakan konversi implisit dari int ke varchar:

SELECT RIGHT(1000 + field, 3)
Konstantin
sumber
4
Namun, itu akan gagal dengan nilai yang cukup besar, lebih lanjut, untuk nilai negatif, Anda akan mendapatkan ... hasil yang menarik.
Nicholas Carey
3

Saya tahu tiket lamanya yang saya pikir akan saya bagikan.

Saya menemukan kode ini mencari solusi. Tidak yakin apakah itu berfungsi pada semua versi MSSQL Saya memiliki MSSQL 2016.

declare @value as nvarchar(50) = 23
select REPLACE(STR(CAST(@value AS INT) + 1,4), SPACE(1), '0') as Leadingzero

mengembalikan "0023" The 4 dalam fungsi STR adalah panjang total termasuk nilai. Contoh 4, 23 dan 123 semuanya akan memiliki 4 dalam STR dan jumlah nol yang benar akan ditambahkan. Anda dapat menambah atau mengurangi itu. Tidak perlu mendapatkan panjang pada tanggal 23.

Sunting: Saya melihat sama dengan posting @Anon.

Niel Beli
sumber
3

Coba ini dengan panjang tetap.

select right('000000'+'123',5)

select REPLICATE('0', 5 - LEN(123)) + '123'
Dr.Stark
sumber
2

Saya memiliki masalah yang sama dengan kolom integer sebagai input ketika saya membutuhkan varchar (atau string) berukuran tetap. Misalnya, 1 hingga '01', 12 hingga '12'. Kode ini berfungsi:

SELECT RIGHT(CONCAT('00',field::text),2)

Jika input juga merupakan kolom varchar, Anda dapat menghindari bagian casting.

pengguna3183867
sumber
2

Untuk pendekatan yang lebih dinamis coba ini.

declare @val varchar(5)
declare @maxSpaces int
set @maxSpaces = 3
set @val = '3'
select concat(REPLICATE('0',@maxSpaces-len(@val)),@val)
ncastillo
sumber
1

Menulis ini karena saya memiliki persyaratan hingga panjang tertentu (9). Pads kiri dengan @pattern SAJA ketika input perlu padding. Harus selalu mengembalikan panjang yang ditentukan dalam @pattern.

declare @charInput as char(50) = 'input'

--always handle NULL :)
set @charInput = isnull(@charInput,'')

declare @actualLength as int = len(@charInput)

declare @pattern as char(50) = '123456789'
declare @prefLength as int = len(@pattern)

if @prefLength > @actualLength
    select Left(Left(@pattern, @prefLength-@actualLength) + @charInput, @prefLength)
else
    select @charInput

Mengembalikan 1234input

Nicky
sumber
1

Sederhana itu

Suka:

DECLARE @DUENO BIGINT
SET @DUENO=5

SELECT 'ND'+STUFF('000000',6-LEN(RTRIM(@DueNo))+1,LEN(RTRIM(@DueNo)),RTRIM(@DueNo)) DUENO
DEBASIS PAUL
sumber
0

Saya datang ke sini secara khusus untuk mencari tahu bagaimana saya bisa mengubah zona waktu saya menjadi string zona waktu untuk mengubah tanggal menjadi DATETIMEOFFSET di SQL Server 2008. Gross, tetapi perlu.

Jadi saya memerlukan 1 metode yang akan mengatasi angka negatif dan positif, memformatnya menjadi dua karakter dengan nol di depan jika diperlukan. Jawaban Anons membuat saya dekat, tetapi nilai-nilai zona waktu negatif akan keluar 0-5daripada yang diperlukan-05

Jadi dengan sedikit perubahan pada jawabannya, ini berfungsi untuk semua konversi jam waktu

DECLARE @n INT = 13 -- Works with -13, -5, 0, 5, etc
SELECT CASE 
    WHEN @n < 0 THEN '-' + REPLACE(STR(@n * -1 ,2),' ','0') 
    ELSE '+' + REPLACE(STR(@n,2),' ','0') END + ':00'
Merah
sumber
-1

Saya membuat fungsi ini yang melayani bigint dan satu nol terkemuka atau karakter tunggal lainnya (maks 20 karakter dikembalikan) dan memungkinkan untuk panjang hasil kurang dari panjang nomor input:

create FUNCTION fnPadNum (
  @Num BIGINT --Number to be padded, @sLen BIGINT --Total length of results , @PadChar varchar(1))
  RETURNS VARCHAR(20)
  AS
  --Pads bigint with leading 0's
            --Sample:  "select dbo.fnPadNum(201,5,'0')" returns "00201"
            --Sample:  "select dbo.fnPadNum(201,5,'*')" returns "**201"
            --Sample:  "select dbo.fnPadNum(201,5,' ')" returns "  201"
   BEGIN
     DECLARE @Results VARCHAR(20)
     SELECT @Results = CASE 
     WHEN @sLen >= len(ISNULL(@Num, 0))
     THEN replicate(@PadChar, @sLen - len(@Num)) + CAST(ISNULL(@Num, 0) AS VARCHAR)
     ELSE CAST(ISNULL(@Num, 0) AS VARCHAR)
     END

     RETURN @Results
     END
     GO

     --Usage:
      SELECT dbo.fnPadNum(201, 5,'0')
      SELECT dbo.fnPadNum(201, 5,'*')
      SELECT dbo.fnPadNum(201, 5,' ')
Shane
sumber