:: Visual Foxpro, Foxpro for DOS
ID++
shumik73
Автор

Сообщений: 522
Откуда: Алматы
Дата регистрации: 10.05.2006
Добрый день
Вопрос добавления новой записи в MSSQL тема не новая, можно сказать детская - но все же хочу еще раз ее затронуть
Может на форуме уже тема разобрана - и ограничится ссылкой. Но пока так быстро не нашёл

Стандартно
1) Есть таблица с данными TABLE1
2) В таблице есть ключевое поле ID int
3) Чтобы гарантировать уникальность и скорость "Создаётся первичный ключ" PRIMATY KEY
4) При добавление вычисляется максимальное значение SELECT MAX(ID) as Count FROM TABLE1 и значение присваивается переменной nRow
5) Далее команда добавления - тут 2 варианта решения

вариант №1 - сразу добавить все значения в одной команде
INSERT INTO (ID,.....) VALUES (<nrow+1>,...)

вариант №2 - добавляется с строка с новым ID, потом прописываются остальные значения
INSERT INTO (ID) VALUES (<nrow+1>)
UPDATE TABLE SET X=.., Y=.. WHERE ID=<nrow+1>


Работа с документами (записями) привела к созданию двух универсальных функций (выбор ключа и обновление по ключу):
  • При редактирование запоминается текущий nrow
  • При добавление вычисляется max(nrow)+1
    А далее для обоих режимов UPDATE TABLE SET X=.., Y=.. WHERE ID=<...>

    Но у Варианта №2 есть и недостатки
    1) При вычисление max(nrow) каким-то образов может вернуть 0, а такой записи быть не должно
    2) Строка с ID добавится а в остальных полях NULL. А при обновление может возникнуть ошибка. После этого в таблице остаются битые строчки и в таблице перестают работать DymanicBackColor

    Поделитесь как более изящно организовать процесс добавления и обновление записей ?
    Возможно в команду обновление сразу включить вычисление нового ключа?


    Есть стандартные средства MSSQL

    CREATE TABLE Table1(ID INT IDENTITY(1,1) NOT NULL, Name VARCHAR(50) NULL, CONSTRAINT PK_Table1 PRIMARY KEY CLUSTERED (ID ASC) )
    SELECT IDENT_CURRENT('TABLE1')
    SELECT @@IDENTITY
    SELECT SCOPE_IDENTITY()

    Но поля IDENTITY не использовал, так как их нужно создавать изначально при создание таблицы и на сколько помню их сложно редактировать
    Ratings: 0 negative/0 positive
  • Re: ID++
    alex;

    Сообщений: 2961
    Откуда: Москва
    Дата регистрации: 23.11.2004
    shumik73
    Но поля IDENTITY не использовал, так как их нужно создавать изначально при создание таблицы и на сколько помню их сложно редактировать

    Мтк, поля IDENTITY можно добавлять и после создания таблицы.
    CREATE TABLE dbo.Tmp_Table_1
    (
    id int NOT NULL IDENTITY (1, 1),
    name nchar(10) NULL
    ) ON [PRIMARY]
    GO
    ALTER TABLE dbo.Tmp_Table_1 SET (LOCK_ESCALATION = TABLE)
    GO
    SET IDENTITY_INSERT dbo.Tmp_Table_1 ON
    GO
    IF EXISTS(SELECT * FROM dbo.Table_1)
    EXEC('INSERT INTO dbo.Tmp_Table_1 (id, name)
    SELECT id, name FROM dbo.Table_1 WITH (HOLDLOCK TABLOCKX)')
    GO
    SET IDENTITY_INSERT dbo.Tmp_Table_1 OFF
    GO
    DROP TABLE dbo.Table_1
    GO
    EXECUTE sp_rename N'dbo.Tmp_Table_1', N'Table_1', 'OBJECT'

    Редактировать поля IDENTITY нельзя.
    Ratings: 0 negative/0 positive
    Re: ID++
    of63

    Сообщений: 25406
    Откуда: Н.Новгород
    Дата регистрации: 13.02.2008
    Поделитесь как более изящно организовать процесс добавления и обновление записей ?
    Возможно в команду обновление сразу включить вычисление нового ключа?


    "Изящности" нет. Добавляй/изменяй записи, и "сам поймешь"
    Ratings: 0 negative/0 positive
    Re: ID++
    sphinx

    Сообщений: 31402
    Откуда: Каменск-Уральски
    Дата регистрации: 22.11.2006
    Я видел решение, что значения всех последних ключей во всех таблицах хранится в специальной табличке.

    Плюсы:
    - не надо вычислять последнее (максимальное) значение ключа, берез из таблицы + 1.

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


    ------------------
    "Veni, vidi, vici!"(с)
    Ratings: 0 negative/0 positive
    Re: ID++
    Дмитрий Петров

    Сообщений: 3075
    Откуда: Пермь
    Дата регистрации: 09.07.2001
    В предыдущем проекте на Оракле много где на сиквенсы id -шники были завязны. Сейчас в postgresql тоже встречается такое.
    Ratings: 0 negative/0 positive
    Re: ID++
    PaulWist

    Сообщений: 14659
    Дата регистрации: 01.04.2004
    Для начала КАК ПРОЧИТАТЬ ЗНАЧЕНИЕ ПОЛЯ СО СВОЙСТВОМ IDENTITY


    ------------------
    Есть многое на свете, друг Горацио...
    Что и не снилось нашим мудрецам.
    (В.Шекспир Гамлет)
    Ratings: 0 negative/0 positive
    Re: ID++
    Каратаев

    Сообщений: 3993
    Откуда: Алматы
    Дата регистрации: 04.12.2001
    sphinx
    А в редкоиспользуемых справочниках вообще стоит автоинкремент.
    А вот действительно, автоинкремент почему бы не использовать?


    ------------------
    Никогда не бывает настолько плохо, чтобы не могло быть еще хуже.
    Ratings: 0 negative/0 positive
    Re: ID++
    sphinx

    Сообщений: 31402
    Откуда: Каменск-Уральски
    Дата регистрации: 22.11.2006
    Саш, это уже обсуждалось неоднократно. Владимир Максимов писал, что-то я, безусловно, подзабыл... Поэтому для журналов вычисляю, а для справочников можно и автоинкремент. Есть справочники, которые меняются условно. Ну какие там проблемы могут быть?


    ------------------
    "Veni, vidi, vici!"(с)
    Ratings: 0 negative/0 positive
    Re: ID++
    PaulWist

    Сообщений: 14659
    Дата регистрации: 01.04.2004
    Какой сокральный смысл в хинтах holdlock tablelockx


    ------------------
    Есть многое на свете, друг Горацио...
    Что и не снилось нашим мудрецам.
    (В.Шекспир Гамлет)
    Ratings: 0 negative/0 positive
    Re: ID++
    alex;

    Сообщений: 2961
    Откуда: Москва
    Дата регистрации: 23.11.2004
    PaulWist
    Какой сокральный смысл в хинтах holdlock tablelockx

    Этот код был сгенерирован в SSMS.
    Думаю, это полная блокировка таблицы перед удалением.

    Так как я убрал begin tran и commit, то смысл теряется. Вы, правы.
    Ratings: 0 negative/0 positive
    Re: ID++
    AndyNigmatec

    Сообщений: 1590
    Откуда: Волгоград
    Дата регистрации: 28.06.2015
    я в firebird для целей получения уникального id сиквенсы (генератор) и использовал - они (сиквенсы) там незавимые и дубликатов не происходит ... может неверное решение, но меня не подводило еще не разу.
    Ratings: 0 negative/0 positive
    Re: ID++
    sphinx

    Сообщений: 31402
    Откуда: Каменск-Уральски
    Дата регистрации: 22.11.2006
    Мы с Сашей Каратаевым больше про фокс. В ПГ сиквенсы. И автоинкременты. Уж не знаю, все ли по фен-шую, или частично...


    ------------------
    "Veni, vidi, vici!"(с)
    Ratings: 0 negative/0 positive
    Re: ID++
    PaulWist

    Сообщений: 14659
    Дата регистрации: 01.04.2004
    При операциях DDL не требуется накладывать боокировки на данные, используются блокировки метаданных модификации схемы.


    ------------------
    Есть многое на свете, друг Горацио...
    Что и не снилось нашим мудрецам.
    (В.Шекспир Гамлет)
    Ratings: 0 negative/0 positive
    Re: ID++
    PaulWist

    Сообщений: 14659
    Дата регистрации: 01.04.2004
    SELECT MAX(ID) as Count FROM TABLE

    Так делать не надо.

    Задача разделяется на две.

    1. Все манипуляции с данными производятся на клиенте в фоксе (RV/SPT), то есть прежде чем отправить данные на сервер надо знать "следующий" PK, в этом случае надо использовать последовательности/ф-ии (SEQUENCE/NewID(), NEWSEQUENTIALID() ).

    В этом случае достаточно послать запрос на сервер

    SQLEXEC(hnd, 'SELECT NEXT VALUE FOR SEQUENCE', 'Seq')

    2. Манипуляция данными с помощью ХП, тогда можно использовать п.1, а так же всякие Scope_Identity(), OUTPUT inserted/deleted итп.


    ------------------
    Есть многое на свете, друг Горацио...
    Что и не снилось нашим мудрецам.
    (В.Шекспир Гамлет)




    Исправлено 1 раз(а). Последнее : PaulWist, 30.04.24 20:51
    Ratings: 0 negative/0 positive
    Re: ID++
    Владимир Максимов

    Сообщений: 14103
    Откуда: Москва
    Дата регистрации: 02.09.2000
    Начать надо с определений

    Primary Key - это поле, по значению которого можно однозначно идентифицировать запись таблицы.

    А вот чем именно является содержимое этого поля - числом или чем-то еще - совершенно не имеет значения. Это может быть GUID, это может быть некий текст, это может быть число или комбинация всего перечисленного

    Просто по содержимому этого поля должна быть возможность однозначно идентифицировать запись. Не должно быть дублей. Все остальные свойства Primary Key - вторичны. Да, эти "вторичные" свойства тоже могут быть важны, но если не решается основная задача однозначной идентификации, то от таких вариантов формирования Primary Key стоит отказаться

    Первый выбор - это выбор между "естественными" и "суррогатными" ключами

    ЕСТЕССТВЕННЫЕ ИЛИ СУРРОГАТНЫЕ КЛЮЧИ

    В общем, лучше использовать "суррогатные" ключи

    Дальше следует определится с типом данных.

  • Целое число
  • Цифро-буквенный идентификатор
  • GUID

    GUID

    Самый простой вариант. Его можно генерировать где угодно и когда угодно. Любой функцией, которая может это делать. В MS SQL это функция NewId(). В рамках любой "самоделки" вполне можно считать, что GUID обеспечивает уникальную идентификацию записи.

    Недостаток GUID (кроме размера в 16 байт) в его "не читабельности". Сложно запомнить "на глаз". Но, тут вопрос в том, что и 10 цифр в качестве идентификатора тоже не очень-то запомнишь

    Цифро-буквенный идентификатор

    Это что-то вроде номера документа. Исходящий/входящий документ, номер заказа. Т.е., вообще-то, это "естественный" ключ, но формирующийся автоматически.

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

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

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


    Целое число

    Ну да. С этого обычно начинают, а не заканчивают Самый же просто вариант. Вот как же! Это как раз самый сложный и проблемный вариант

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

    Для решения проблемы в MS SQL есть следующие варианты

      1. Поля со свойством Identity
      2. Объект Sequence
      3. Отдельная таблица со счетчиками


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

    Из "непонятного" тут разве что объект Sequence. Тут только вопрос в версии MS SQL, поскольку этот объект в младших версиях не существовал. Не в курсе, с какой версии MS SQL он появился, так что тут надо смотреть, есть ли он в той версии, с которой работаешь

    Объект Sequence можно рассматривать именно что как отдельную таблицу со счетчиком к которой организован специфический доступ. Но, может оказаться, что создать собственную таблицу будет более оптимальным решением

    Для свойства Identity ключевой недостаток в том, что значение формируется только после создания записи. Впрочем, в статье, ссылку на которую привел Паша описано, как можно обойти. Тут надо смотреть по решаемой задаче, подойдет ли такое решение или нет

    С целыми числами также будут проблемы при репликации (объединении баз данных) приложений. Есть разные варианты решений, но с ограничениями

    В общем, целое число как Primary Key - это интуитивно понятное, но, как ни странно, самое сложное решение с точки зрения дальнейшего развития приложения.
    Ratings: 0 negative/0 positive
  • Re: ID++
    of63

    Сообщений: 25406
    Откуда: Н.Новгород
    Дата регистрации: 13.02.2008
    > В общем, целое число как Primary Key - это интуитивно понятное
    Владимир, не усложняйте, и не упрощайте. "Интуитивное" - это не причина чего-либо, сами знаете

    ()() Чекнулся сначала ... Володя, . Очсисторожнее с высказываниями.
    Хотя, я против тормозов.
    Спс за всякое при ВФП SQL=ЯП использовании )

    () прогерство, и математика, и просто энтузиазм, как были, так и остались движем "")



    Исправлено 3 раз(а). Последнее : of63, 03.05.24 00:08
    Ratings: 0 negative/0 positive


    Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

    On-line: 17 (Гостей: 17)

    © 2000-2024 Fox Club 
    Яндекс.Метрика