TSQL Вставить загадку - PullRequest
0 голосов
/ 07 мая 2009

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

RefID | TypeID
    1 | 1
    1 | 3
    1 | 6
    2 | 3
    3 | 5
    3 | 6

Где первый столбец - ссылка на местоположение, а второй - фактические значения.

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

ID | RefID | TypeID
1  | 1   | 1
2  | 1   | 3
3  | 1   | 6
4  | 4   | 3
5  | 5   | 5
6  | 5   | 6

Таким образом, столбец автономного номера (столбец 1) выступает в качестве начального числа для ссылочного столбца.

Таким образом, у меня есть две проблемы - копирование значения столбца идентификатора в ссылочный столбец и возврат справочного значения в приложение, чтобы его можно было использовать, если для местоположения существует более одного значения.

Я придумал эту хранимую процедуру:

CREATE PROCEDURE [dbo].[AddCaseType]
(
    @TypeID INTEGER,
    @CaseID INTEGER = NULL OUT 
)
AS
BEGIN

    INSERT INTO
        dbo.CaseTypeList(RefID, TypeID)
    VALUES
         ( ISNULL(@CaseID,SCOPE_IDENTITY()), @TypeID)

    Set @CaseID =  SCOPE_IDENTITY()
END
GO

ISNULL проверяет наличие NULL в CaseID и, если оно пустое, использовать значение SCOPE_IDENTITY(). Однако SCOPE_IDENTITY вычисляется до вставки и, таким образом, возвращает последний сгенерированный идентификатор, а не новый.

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

Так что я знаю, что хочу делать, но просто не обладаю знаниями или опытом, чтобы это делать.

Итак, для инкапсуляции: Как я могу сгенерировать уникальное значение для первого элемента набора и вернуть это значение, чтобы я мог повторно использовать его для остальной части этого набора?

Также вы можете ответить, если есть другой, более простой способ. Пожалуйста, помните - я новичок в SQL, поэтому мне нужно понять, почему что-то происходит, потому что мне может понадобиться изменить это в будущем.

Обновление : После захвата кофе я заметил ошибку в своем коде - результат изменения трех столбцов, поэтому [ID] становится RefID в первой части инструкции INSERT. Это также делает недействительным часть кода и, таким образом, частично меняет природу моей проблемы. Извините за путаницу, это может вызвать.

1 Ответ

5 голосов
/ 07 мая 2009

При вставке в таблицу со столбцом identity вы ничего не указываете для столбца identity:

DECLARE @ERR INT

INSERT INTO CaseTypeList (TypeID, CaseID) --Column1 is auto-number, skip it
VALUES (@TypeID, @CaseID)

-- capture error var and last inserted identity value
SELECT @ERR = @@ERROR, @ID = SCOPE_IDENTITY()

-- IF @ERR <> 0 handle error, otherwise return

Вам не нужно вставлять идентификационные данные или что-то подобное, если только вы не хотите явно контролировать номер. В этом случае вы не установите его на identity.

Кроме того, я вроде как догадался о ваших столбцах.


Редактировать: ОК, похоже, вам на самом деле не нужен столбец идентификаторов вообще. Вместо этого вам нужно сгенерировать следующее число в последовательности, если оно не указано. В этом случае вы можете оставить там столбец идентификаторов - это не повредит, но может помочь позже, если вам нужен единственный уникальный ключ:

CREATE PROCEDURE [dbo].[AddCaseType]
(
    @RefID     INTEGER = NULL OUT,
    @TypeID    INTEGER
)
AS

BEGIN TRANSACTION

  IF @RefID IS NULL BEGIN
    SELECT @RefID = MAX(RefID)+1 FROM CaseTypeList
  END

  IF @@ERROR <> 0 BEGIN ROLLBACK; RAISERROR('Could not get ID', 16, 1) END


  INSERT INTO
    CaseTypeList(RefID, TypeID)
  VALUES
    (@RefID, @TypeID)

  IF @@ERROR <> 0 BEGIN ROLLBACK; RAISERROR('Could not insert', 16, 1) END

COMMIT TRANSACTION 

Примечание: вы, вероятно, должны иметь ограничение уникального ключа для RefID и TypeID, если не может быть дубликатов.

...