SQL Server - Identity column as a primary key

User avatar
katit
Уже с Приветом
Posts: 23804
Joined: 05 Jul 2003 22:34
Location: Брест -> St. Louis, MO

Post by katit »

Dmitry67 wrote:если Вы это делаете в отдельной транзакции. Если в транзакции вы заранее не знаете сколько и какие объекты будете вставлять то либо ваши изменения счетчика попадут в транзакцию, либо их надо делать в отдельной коннекции.


Да, там по старинке. Каждому клиенту - по соединению.
User avatar
AnyaGal
Уже с Приветом
Posts: 5771
Joined: 02 Dec 1999 10:01
Location: Saint-Petersburg --> Bellevue, WA

Post by AnyaGal »

Чего-то я вообще запуталась. :)

Мне собственно надо создать небольшую content managment систему для сайта нашей компании для пользователей.

То есть чтобы кто-то из нашего CS мог через web страницы выбрать категорию нашего продукта, сам продукт, его версию, номер патча/билда/сервис пака и т.д и добавить информацию для пользователя, путь к файлу, который можно прочитать или сделать upload/download.
Также выбрать дату когда вся эта информация expired. Все это сохраняется в БД.

А в run time для пользователя все ASP страницы генерятся автоматически и информация берется из БД.

То есть в БД будут такие таблицы как ProductCategory, Product, ReleaseGroup, ReleaseElement, ProductVersion, уникальных названий для всех этих категорий можно сказать нет, или есть но длинные, и которые могут менятся со временем. Я конечно могу для них придумать сокращения, но их надо будет всем помнить.

Но я боюсь, что разные люди из разных отделов уже используют свои сокращенные названия.

Какие мне все-таки выбрать ключи - естественные или искусственные s Identity?

Kонтроль за всякими constraints i cascade delete/update могу установить - тут моя вотчина, начинаю с нуля, чего хочу того и ворочу :) , поэтому хочется сделать как лучше.
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

katit wrote:
Dmitry67 wrote:если Вы это делаете в отдельной транзакции. Если в транзакции вы заранее не знаете сколько и какие объекты будете вставлять то либо ваши изменения счетчика попадут в транзакцию, либо их надо делать в отдельной коннекции.


Да, там по старинке. Каждому клиенту - по соединению.


Да нет
Вам каждому клиенту нужно ДВА соединения
Либо система достаточна примитивна и например за раз вставляет только один объект. Тогда Вы можете заранее открутить счетчик в отдельной транзакции
Наконец, можно даже предположить что Вы читаете счетчик в readuncommitted, но не думаю что так у вас делают. Впрочем, и в жтом случае есть засады
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

AnyaGal wrote:Какие мне все-таки выбрать ключи - естественные или искусственные s Identity?


Увы
Этот спор так же стар как C vs pascal
На эту тему сломано бесчисленное множество копий
Спор отчасти из разряда религиозных
А что лучше... как говаривал старина Малдер, the truth is out there
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
katit
Уже с Приветом
Posts: 23804
Joined: 05 Jul 2003 22:34
Location: Брест -> St. Louis, MO

Post by katit »

Dmitry67 wrote:Либо система достаточна примитивна и например за раз вставляет только один объект. Тогда Вы можете заранее открутить счетчик в отдельной транзакции


Наверное примитивна :pain1:
Как правило счетчик обрабатывается вне транзакции. Если пролет - то пролет. Пробелы не запoлняются.
User avatar
AnyaGal
Уже с Приветом
Posts: 5771
Joined: 02 Dec 1999 10:01
Location: Saint-Petersburg --> Bellevue, WA

Post by AnyaGal »

Хорошо, если выбрать Identity, то какие основные неудобства в работе меня ожидают и как их избижать или преодолеть малой кровью?
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

katit wrote:
Dmitry67 wrote:Либо система достаточна примитивна и например за раз вставляет только один объект. Тогда Вы можете заранее открутить счетчик в отдельной транзакции


Наверное примитивна :pain1:
Как правило счетчик обрабатывается вне транзакции. Если пролет - то пролет. Пробелы не запoлняются.


Вот в этом и проблема
А если в одной транзакции вставляется заранее неизвестное количество объектов то ...

Впрочем у меня самого так было... система была тянута с Btrieve, а там identity не было
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
katit
Уже с Приветом
Posts: 23804
Joined: 05 Jul 2003 22:34
Location: Брест -> St. Louis, MO

Post by katit »

Dmitry67 wrote:Вот в этом и проблема
А если в одной транзакции вставляется заранее неизвестное количество объектов то ...


Не понимаю в чем проблема.

Вот это код процедуры:

Code: Select all

begin transaction
   UPDATE tciSurrogateKey
      SET NextKey = CASE NextKey
                    WHEN 2147483647 THEN 1
                    ELSE NextKey + 1                   
                    END
    WHERE TableName = @iTableName

   IF @@rowcount = 0
   BEGIN
      INSERT tciSurrogateKey
            (TableName
            ,NextKey)
      VALUES(@iTableName
            ,2)
   END
   
   SELECT @oNewKey = CASE NextKey
                     WHEN 1 THEN 2147483647
                     ELSE NextKey - 1
                     END
     FROM tciSurrogateKey
    WHERE TableName = @iTableName

   commit transaction
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

AnyaGal wrote:Хорошо, если выбрать Identity, то какие основные неудобства в работе меня ожидают и как их избижать или преодолеть малой кровью?


Неудобства заключаются в следуюшем
Если данные глобальны, то есть передаются между серверами, то придется вести xref tables. Либо использовать guid (но у низ свои неудобства)

По таблице с identity не создать partitioned table. Но вряд ои Вам жто нужно

Главное, если вставляется в стиле insert ... select много записей. то понятно @@identity недостаточно. Копирование документов в identity-based snowflake schema - это мука. Люди пишут циклы (без циклов копирование написать довольно сложно но можно)

Поэтому в случае зранения документов я рекомендую star, ну или смесь snowflake и star, так чтобы каждая запись имела непосредственный выход на корень
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

katit, дело не в процедуре

Вы даеете так
exec GetCounter 'mytab', @cnt output
begin transaction
exec InsMyTab @cnt,'my data'
commit transaction

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

exec GetCounter 'mytab', @cnt output
begin transaction
exec InsMyTab @cnt,'my data 1'
exec GetCounter 'mytab', @cnt output
exec InsMyTab @cnt,'my data 2'
commit transaction

Проблема в том что если создать два документа вы должны в одной транзакции, то getCounter в любом случае окажется внутри, и будет держать блокировку на счетчик (думаю вы знаете что после commit внутри теле процедуры счетчика блокировку не сбросит и транзакцию не завершит, а просто уменьшит счетчик с 2 до 1)
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
AnyaGal
Уже с Приветом
Posts: 5771
Joined: 02 Dec 1999 10:01
Location: Saint-Petersburg --> Bellevue, WA

Post by AnyaGal »

Dima, спасибо, но масштаб у этого проэкта я надеюсь другой.
:)
User avatar
katit
Уже с Приветом
Posts: 23804
Joined: 05 Jul 2003 22:34
Location: Брест -> St. Louis, MO

Post by katit »

А. Вы про это.
У нас такого не бывает. Т.е. Вставляется или одна запись или множество.

Во втором случае всегда есть #таблица в которой все накапливается.
Далее вызывается другая СП:

Code: Select all

if @iFrequency = 0
    begin
        select @oStartKey = 0
        select @oEndKey = 0
        return
    end

    set ARITHIGNORE on
    begin transaction
    update tciSurrogateKey
        set NextKey = case NextKey + @iFrequency
                    when null then @iFrequency + 1  -- in case of overflow
                    else NextKey + @iFrequency
                    end
        where TableName = @iTableName

    if @@rowcount = 0
    begin   
        insert tciSurrogateKey
            (TableName
            ,NextKey)
        values (@iTableName
            ,@iFrequency + 1)
    end
   
    select @oStartKey = case NextKey
                    when @iFrequency + 1 then 1
                    else NextKey - @iFrequency
                    end
    from tciSurrogateKey
    where TableName = @iTableName

    select @oEndKey = @oStartKey + @iFrequency - 1

    commit transaction


И после эти дела UPDATE загоняются в #таблицу. Далее идет простой INSERT
[/code]
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Post by Dmitry67 »

Понятно, согласен
Когда логика такая то конечно проблемы нет
Сейчас прочто часто системы где после begin transaction идет вызов метода CreateSomeDocumentsBasedOnOurBusinessLogic, and you have no idea what kind of documents will be created, and how many
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
Sergey___K
Уже с Приветом
Posts: 13014
Joined: 10 Jul 2001 09:01
Location: VA

Post by Sergey___K »

Смотрите, осторожно с Access'овскими AutoIncrement. Например, если из таблицы удалить все записи, а потом сделать Repair, Compact, то она начнет нумеровать сначала. Если ваша Referential Integrity фиговая (а я так понял, что фиговая), то будете иметь с этого потенциальные проблемы,. Если вам так уже влом делать синтетический PK, гляньте на Replication ID, как подтип AutoIncrement.

Return to “Вопросы и новости IT”