Форматирование чисел путем заполнения начальных нулей в 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

Если EmployeeID7135, этот запрос должен вернуться 007135.


Поскольку ведущие 0s важны для этого поля, зачем INTвообще менять его на?
Одед

2
В SQL Server 2012 наконец-то появится такая FORMATфункция, как C # :-)
marc_s

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

Вы оптимизируете до того, как столкнетесь с проблемой?
Одед

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)

И код для удаления этих нулей и возврата «реального» числа:

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

1
+1 Вы мне даже показали, как убрать нули! Позвольте мне проверить это, и я отмечу это как ответ.
jp2code 01

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

2
Это работает, только если переданное значение является строкой. Если вы передадите целое число, вы получите то же значение, которое передали.
Морди,

2
Хотя его старый ... использование "+ convert (varchar, EmployeeID)" вместо "+ EmployeeID" должно решить проблему с int
Кришна Сарма

3
это хороший способ, если только значение EmployeeId не превышает 6 цифр, что приводит к результату NULL. Ответом является функция контакта: SELECT CONCAT (REPLICATE ('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 01

19
Тем не менее, я хотел бы сейчас увидеть этот пузырь немного ближе к вершине.
Дэйв Хейнс

4
На всякий случай кому интересно. Formatне сохраняет тип данных, но неявно преобразуется в nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ральф

2
Это самый простой и ИМХО лучший способ.
Роберт Луджо

Помните об этой функции, если вы используете ее для большого набора данных
amd

33

Вы можете изменить свою процедуру таким образом

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

Однако это предполагает, что EmployeeIDэто числовое значение, и этот код меняет результат на строку, я предлагаю снова добавить исходное числовое значение

ИЗМЕНИТЬ Конечно, я не внимательно прочитал вопрос выше. В нем говорится, что это поле, char(6)поэтому EmployeeID не является числовым значением. Хотя этот ответ по-прежнему имеет ценность, он не является правильным ответом на поставленный выше вопрос.


Я думаю, это самый чистый способ сделать это. Спасибо
iheartcsharp

Это '000000'действительно необходимо ..? '0'тоже работает нормально. Безопасно ли использовать только один 0 ..?
шашват 04

1
OP запросил строку длиной 6 символов в результате. В частности, если EmployeeID равен 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

2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0

Упс. Собственно, это дало мне, 7135.0когда я его дал 7135.
jp2code 01

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

Самое простое - всегда лучшее:

Select EmployeeID*1 as EmployeeID 

-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.