Форматування чисел шляхом прокладки з провідними нулями в SQL Server


119

У нас є стара таблиця SQL, яку SQL Server 2000 використовував близько 10 років.

У ньому наші номери працівника значок зберігаються як char(6)від 000001до 999999.

Зараз я пишу веб-додаток, і мені потрібно зберігати номери значків співробітників.

У своїй новій таблиці я міг би скористатися скороченням і скопіювати стару таблицю, але сподіваюся на кращу передачу даних, менший розмір тощо, просто зберігаючи intзначення від 1до 999999.

У C # я можу швидко відформатувати intзначення для номера значка за допомогою

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

Як я можу змінити цей простий SQL-запит для форматування повернутого значення?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

Якщо EmployeeIDце 7135, цей запит повинен повернутися 007135.


Оскільки провідні 0s важливі для цього поля, навіщо взагалі змінювати його на "a" INT?
Одід

2
Нарешті, SQL Server 2012 матиме таку FORMATфункцію, як C # :-)
marc_s

1
@ Oden: intЗначення займають значно менше місця char(6), і буде створено кілька цих записів на частину, яка буде виготовлена. Ефективність.
jp2code

Ви оптимізуєтесь, перш ніж виникли проблеми?
Одід

4
Подивимось, у вас є до одного мільйона чисел значків, і ви вважаєте, що ви можете зберегти (відповідно DATALENGTH()) два байти кожен. Оскільки стовпець може бути в індексі, ви можете зекономити більше 2 Мб. І з додаванням інших стовпців, що 2 байти може бути достатньо, щоб зменшити довжину рядка, щоб зберегти сторінку в 4 КБ на рядок. Чи буде це розміщуватися на мобільній платформі, чи ви можете зосередити свою увагу на непродуктивній зоні?
HABO

Відповіді:


172

Змініть число 6 на будь-яку загальну довжину:

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

Якщо стовпець є INT, ви можете використовувати RTRIM для неявного перетворення його у VARCHAR

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

І код, щоб зняти ці 0 і отримати "справжнє" число:

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

1
+1 Ви навіть показали мені, як зняти 0! Дозвольте перевірити це, і я позначу це як відповідь.
jp2code

вам не потрібен код для видалення нулів, просто призначте або перетворите на int, і вони будуть видалені автоматично.
Джимбо

2
Це працює лише в тому випадку, якщо передане значення є рядком, якщо ви передаєте ціле число, ви отримаєте те саме значення, яке ви передали.
Mordy

2
Хоча його старе ... використання "+ conver (varchar, EmployeeEID)" замість "+ EmployeeeID" повинно вирішити проблему Int
Кришна Сарма

3
це хороший спосіб, якщо працівник не повинен перевищувати 6 цифр, що призводить до NULL результату. Контактна функція - це відповідь: ВИБІРТИ КОНЦАТ (ЗАМОВИТИ ('0', 6-LEN (CONVERT (varchar, EmployeeId))), EmployeeId)
Махмуд Моравей

125

Просто використовуйте функцію FORMAT (працює на SQL Server 2012 або новіших версіях):

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

Довідка: http://msdn.microsoft.com/en-us/library/hh213505.aspx


1
Це старе питання - до появи SQL Server 2012.
jp2code

19
І все-таки я хотів би зараз побачити цю бульбашку трохи ближче до вершини.
Дейв Хейнес

4
Про всяк випадок, коли хтось цікавиться. Formatне зберігає тип даних, але неявно перетворюється на nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ральф

2
Цей спосіб є найпростішим, а IMHO - найкращим рішенням.
Роберт Луйо

Будьте в курсі цієї функції, якщо ви використовуєте її для великого набору даних
amd

33

Ви можете змінити процедуру таким чином

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

Однак це передбачає, що ваш EmployeeIDчислове значення, і цей код змінює результат на рядок, я пропоную знову додати початкове числове значення

EDIT Звичайно, я не уважно прочитав вищезазначене питання. У ньому йдеться про те, що поле є char(6)таким, що EmployeeeID не є числовим значенням. Хоча ця відповідь сама по собі все ще має значення, це не є правильною відповіддю на вищезазначене питання.


Це найчистіший спосіб зробити це, я думаю. Дякую
iheartcsharp

Це '000000'справді потрібно ..? '0'також добре працює. Чи безпечно використовувати лише один 0 ..?
shashwat

1
ОП попросила в результаті отримати рядок довжиною 6 символів. Зокрема, якщо EmployeeeID становить 7135, цей запит повинен повертати 007135 . Використання лише одного "0" повертає 07135не 007135. Вся ідея полягає в тому, щоб об'єднатись у 6-рядовий рядок, що складається з усіх 0перетворених рядків EmployeedID, а потім ПОЧАТКИ з правого краю візьміть 6 символів. Незалежно від довжини ідентифікатора, метод, наведений вище, завжди повертає рядок із простою кількістю нульових знаків, необхідних для досягнення 6 знаків
Стів

Це може бути 5 нулів, '00000'оскільки заголовок EmployeeIDбуде містити принаймні одну цифру. Але ця REPLICATE()функція здається більш придатною, як і в інших відповідях
nosklo

26

Ненавиджувати ПОВЕРНЕННЯ int, і це здається набагато простішим. Можливо, навіть краще, оскільки існує лише одне перетворення рядків і просте додавання.

виберіть ПРАВО (1000000 + EmployeeId, 6) ...

Просто переконайтесь, що "1000000" має принаймні стільки нулів, скільки потрібно.


11

Я розміщую все в одному місці, все працює для мене, щоб прошивати 4 провідними нулями :)

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

Це охоплює всі необхідні варіанти. Дякую.
kyurthich

6

Ще один спосіб, просто для повноти.

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

Або, відповідно до вашого запиту

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

@ jp2code - вам потрібно прочитати, що таке StackOverflow - його спільно редагувати як вікі - це не ваше питання, як тільки ви його опублікували! Речі, які зазвичай редагуються, - це надмірний "пух", як заздалегідь подяка та погана граматика / велика література.
Jamiec


4

Настільки ж чисті, наскільки це можливо, і дають можливість замінити змінні:

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

Якщо EmployeeIDстовпець визначений як, intто оператор + буде розглядатися як додавання, а не конкатенація, і нулі будуть втрачені. Використання convertдозволить уникнути цієї проблеми.

Виклик REPLICATE ('0', 6), щоб уникнути набору '000000', просто марно ;-)
Младен Михайлович

3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0


1

Рішення працює для підписаних / негативних чисел з провідними нулями для всіх версій Sql:

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

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


-1

У моїй версії SQL я не можу використовувати REPLICATE. Так я зробив це:

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.