MAX / ORDER BY на столбце char - PullRequest
       2

MAX / ORDER BY на столбце char

1 голос
/ 01 декабря 2010

в моей базе данных SQL Server 2005 У меня есть столбец RMA_Number с типом данных char (10) в таблице RMA.

Значение представляет собой возрастающее число в формате RMA0002511.Какой самый быстрый способ получить наибольшее число, чтобы увеличить его при вставке?

Мой первый подход был:

SELECT     TOP (1) RMA_Number
FROM         RMA
WHERE     (RMA_generated = 1)
ORDER BY Creation_Date DESC

Но это было подвержено ошибкам, потому что было возможно, что более высокоеRMA_Number имеет более раннюю дату создания.В качестве обходного пути работает сортировка по первичному ключу:

SELECT     TOP (1) RMA_Number
FROM         RMA
WHERE     (RMA_generated = 1)
ORDER BY idRMA DESC

Но, возможно, это также является возможным источником ошибки.

Логически лучшим способом было бы ORDER BY RMA_Number DESC.

Но поскольку я не был уверен, дает ли это всегда правильный результат, и думал, что сортировка столбца char может замедлиться, если число записей увеличится, я решил упорядочить по столбцу Date.

Итак,

  1. Это хорошая идея, чтобы заказать по столбцу char (10) (производительность и точность)?
  2. было бы лучше SELECT MAX( RMA_Number ) FROM RMA, чтобы получитьнаибольшее число (перф. и точность)
  3. я должен придерживаться использования первичного ключа для заказа, если первые две точки неверны, или я должен использовать столбец int и отформатировать число в приложении?

РЕДАКТИРОВАТЬ :

Я думаю, что должен уточнить кое-что, что я не упомянул.RMA_Number не генерируется при каждой вставке.Так что, может быть, есть много записей без номера.Мартин использует первичный ключ для построения числа.Это было бы проблемой, потому что разрывы были бы слишком большими.

Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 01 декабря 2010

Самый быстрый и безопасный (для параллелизма) способ - вообще не хранить префикс RMA000....

Просто создайте столбец с целочисленной идентификацией и добавьте префикс через вычисляемый столбец.

create table #RMA
(
id int identity(2511,1) primary key,
RMA_Number as 'RMA' + RIGHT('000000' + CAST(id as varchar(7)),7)
)

insert into #RMA
default values

select * from #RMA

Или, следуя новой информации о том, что не все записи имеют RMA_Number, вы можете использовать этот подход для неблокирующего, эффективного и безопасного параллелизма решения.

CREATE TABLE dbo.Sequence(
 val int IDENTITY (2511, 2) /*Seed this at 1 + whatever your current max value is*/
 )

GO

/*Call this procedure to get allocated the next sequence number to use*/     
CREATE PROC dbo.GetSequence
@val AS int OUTPUT
AS
BEGIN TRAN
    SAVE TRAN S1
    INSERT INTO dbo.Sequence DEFAULT VALUES
    SET @val=SCOPE_IDENTITY()
    ROLLBACK TRAN S1 /*Rolls back just as far as the save point to prevent the 
                       sequence table filling up. The id allocated won't be reused*/
COMMIT TRAN
3 голосов
/ 01 декабря 2010

Прежде всего, вы смотрите на серьезное состояние гонки.

Когда нам нужно было это в проекте, с которым мы работали, у нас была отдельная таблица с текущим значением, сохраненным в нем, и функция для генерации следующего. Мы реализовали блокировку, чтобы сохранить несколько вызовов, чтобы получить следующий номер. Насколько я помню, это было потому, что мы должны были использовать буквенно-цифровые идентификационные номера (функция позаботилась о сложном увеличении этого числа).

Однако мне больше всего нравится решение @ Martin: поле use и IDENTITY. Вы можете либо удалить префикс, как он предлагает, либо вы можете просто удалить его из столбца и добавить его обратно при SELECT входе в таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...