Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];

Вниз

Уникальные значения в MSSQL 2000   Найти похожие ветки 

 
Mitrofan   (2004-05-13 09:22) [0]

Скажите, имеется ли в MSSQL 2000 механизм автоинкремента или генераторы ? Как в данной СУБД для поля организовать уникальность значений ? Спасибо.


 
Nikolay M. ©   (2004-05-13 09:24) [1]

IDENTITY


 
Mitrofan   (2004-05-13 09:28) [2]

А как оно работает ? Значение присваивается при вставке записи ?
Могу ли я это значение получить на клиентской машине еще до вставки записи ?


 
31512 ©   (2004-05-13 09:33) [3]

Из справки по Transact-SQL

@@IDENTITY
Returns the last-inserted identity value.

Syntax
@@IDENTITY

Return Types
numeric

Remarks
After an INSERT, SELECT INTO, or bulk copy statement completes, @@IDENTITY contains the last identity value generated by the statement. If the statement did not affect any tables with identity columns, @@IDENTITY returns NULL. If multiple rows are inserted, generating multiple identity values, @@IDENTITY returns the last identity value generated. If the statement fires one or more triggers that perform inserts that generate identity values, calling @@IDENTITY immediately after the statement returns the last identity value generated by the triggers. The @@IDENTITY value does not revert to a previous setting if the INSERT or SELECT INTO statement or bulk copy fails, or if the transaction is rolled back.

@@IDENTITY, SCOPE_IDENTITY, and IDENT_CURRENT are similar functions in that they return the last value inserted into the IDENTITY column of a table.

@@IDENTITY and SCOPE_IDENTITY will return the last identity value generated in any table in the current session. However, SCOPE_IDENTITY returns the value only within the current scope; @@IDENTITY is not limited to a specific scope.

IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope. For more information, see IDENT_CURRENT.

Examples
This example inserts a row into a table with an identity column and uses @@IDENTITY to display the identity value used in the new row.

INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ("Accountant",12,125)
SELECT @@IDENTITY AS "Identity"


 
Jee ©   (2004-05-13 09:40) [4]


> 31512 ©   (13.05.04 09:33) [3]

И какая мораль следует из цитирования хэлпа?
@@IDENTITY, SCOPE_IDENTITY, and IDENT_CURRENT - вещи хорошие. Однако если ты сам работаешь с таблицей и если добавляются строки с нескольких клиентов, ситуации немножко разные, не так ли?


 
Курдль ©   (2004-05-13 09:49) [5]

У меня есть на такие случаи общее пожелание.
1. Потратьте немного времени на ознакомление (пусть даже не углубленное изучение) CASE - технологий.
2. Установите себе какое-нибудь средство CASE хотя самый минимальный набор для работы с БД. Это может быть от тяжеловесного монстра Rational Rose до компактного PD.
3. Потренируйтесь немного в проектировании БД - от концептуальной модели - к физической и до генерации скрипта создания БД.
4. Внимательно посмотрите скрипт и вы обязательно удивитесь, как грамотно все вышло!
Т.е. если у Вас в концептуальной модели стояло поле "ID serial", то простой заменой целевой СУБД в скрипте можно получить:
- для IB - CREATE GENERATOR
- для Oracle - CREATE SEQUENCE
и т.д.
Таблицы автоматически будут снабжены всем необходимым - ключами, индексами, констрэйнтами, а ошибки будут отловлены еще до генерации самой БД.


 
bushmen ©   (2004-05-13 13:24) [6]

Я бы для начала поссоветовал поглубже изучить основы MS SQL Server"a, а также основы клиент-серверной технологии


 
31512 ©   (2004-05-14 09:51) [7]


> Jee ©  


> И какая мораль следует из цитирования хэлпа?


Мораль сей басни такова:
Посмотрим хелп сначала,
И не найдя ответа,
Возми и умну книжку почитай
Или сходи до интернета.
И лишь потом вопросы
В форум посылай ...
          31512 ©
P.S.

В [1] про

> если добавляются строки с нескольких клиентов

ничего не сказано.


 
Jee ©   (2004-05-14 10:18) [8]


> 31512 ©   (14.05.04 09:51) [7]

Мораль конечно замечательная. Таким образом можно ответить на 99% вопросов в форуме, при этом можно даже не знать ответа.
В [1] ответили достаточно для того, чтобы человек нашел сам в хэлпе.

> > если добавляются строки с нескольких клиентов
>
> ничего не сказано.

Ничего не сказано и про то, что с MSSQL 2000 в данном случае будет работать исключительно один клиент. Имхо, если используется такого класса СУБД, нужно рассчитывать на то, что это будет не так. Человек начнет использовать значение IDENTITY в могопользовательском режиме и отгребет кучу ошибок.


 
Jee ©   (2004-05-14 10:22) [9]


> Mitrofan   (13.05.04 09:28) [2]
> А как оно работает ? Значение присваивается при вставке
> записи ?
> Могу ли я это значение получить на клиентской машине еще
> до вставки записи ?

Можно конечно и с IDENTITY сделать корректно, но придется изворачиваться, чтобы не возникло конфликтов при вставках записей с разных клиентов.
Если тебе действительно необходимо на клиентской машине перед вставкой записи получать уникальное значение ключа, можно использовать тип uniqueidentifier у поля. А занчение получать функцией NEWID(). Но за это придется поплатиться объемом данных.


 
Nikolay M. ©   (2004-05-14 10:54) [10]


> начнет использовать значение IDENTITY в могопользовательском
> режиме и отгребет кучу ошибок.

SCOPE_IDENTITY() в большинстве случаев вполне достаточно.


 
31512 ©   (2004-05-14 10:54) [11]


> Jee ©   (14.05.04 10:18) [8]


Таки Игорь прав ...

http://ln.com.ua/~openxs/articles/smart-questions-ru.html


 
Danilka ©   (2004-05-14 11:10) [12]

[9] Jee ©   (14.05.04 10:22)
Только этот ID будет мало похож на автоинкремент, мягко говоря. :)
Получить автоинкрементированое значение перед вставкой записи может понадобиться, например, для автонумерации документов, а теперь представь что будет, если в номере договора напишется это самое. :))


 
Skyle ©   (2004-05-14 11:19) [13]


> Но за это придется поплатиться объемом данных.

И ещё, если я не ошибаюсь, без приведения типов по полю типа uniqueidentifier нельзя сортировать.

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


 
Jee ©   (2004-05-14 11:32) [14]


> 31512 ©   (14.05.04 10:54) [11]

Спасибо за ссылку, весьма интересная статья.

> Таки Игорь прав ...

Это кто?


> Skyle ©   (14.05.04 11:19) [13]

uniqueidentifier удобен, например, в случае, когда есть несколько баз, находящихся в разных филиалах. И есть центральная база в офисе. Данные из филиалов собираются в центральную базу. При добавлении строк не возникнет конфликта с уникальностью первичного ключа.
А по поводу использования ПК для сортировки, номера документа и т.п. - он не для этого предназначен. Корректнее использовать специальные поля.


 
Danilka ©   (2004-05-14 11:37) [15]

[14] Jee ©   (14.05.04 11:32)
А ПК, как правило, и не требуется знать до вставки записи.
Конечно, пусть автор ветки скажет для чего это ему нужно, но если мой мелафон в порядке, то тогда uniqueidentifier ему не подойдет. :))


 
Skyle ©   (2004-05-14 11:40) [16]


> uniqueidentifier удобен, например, в случае, когда есть
> несколько баз, находящихся в разных филиалах.

С этим я спорить не буду, но в данном случае никакой нагрузки кроме обеспечения глобальной уникальности при синхронизации он не несёт.


> При добавлении строк не возникнет конфликта с уникальностью
> первичного ключа.

А на кой ему быть первичным ключом, если он используется только между базами? Пусть первичным ключом будет ID INT IDENTITY(1, 1), а UID - где-нибудь там же, но сбоку. Выскажу предположение, что индекс по ID будет веселее строиться, чем по UID.


> А по поводу использования ПК для сортировки, номера документа
> и т.п. - он не для этого предназначен. Корректнее использовать
> специальные поля.

А я как сказал? :-)


 
-=VaaL=- ©   (2004-05-14 11:46) [17]

ндааа... а теперь еще раз прочитаем цитирование хелпа 31512 ©   (13.05.04 09:33) [3]

@@IDENTITY and SCOPE_IDENTITY will return the last identity value generated in any table in the current session.


 
Skyle ©   (2004-05-14 12:07) [18]


> -=VaaL=- ©   (14.05.04 11:46) [17]
> ндааа... а теперь еще раз прочитаем цитирование хелпа 31512
> ©   (13.05.04 09:33) [3]
>
> @@IDENTITY and SCOPE_IDENTITY will return the last identity
> value generated in any table in the current session.

И что? Судя по

> Mitrofan   (13.05.04 09:28) [2]
> А как оно работает ? Значение присваивается при вставке
> записи ?
> Могу ли я это значение получить на клиентской машине еще
> до вставки записи ?

IDENTITY тут никак не катит и о нём вообще речи нет.
Автор к сожалению никак не конкретизировал задачу.
Или я чего-то не понял?


 
paul_k ©   (2004-05-14 13:41) [19]

выкрутится можно следующим путем
CREATE TABLE t_all_ids (
id numeric(18, 0) IDENTITY (1, 1) NOT NULL,
user_login numeric(18, 0) IDENTITY (1, 1) NOT NULL,
)

go

create procedure GetId New_Id numeric  output
as
begin tran
insert into t_all_ids (user_login)
select suser_sname()
set New_Id =  @@identity
Commit tran
go
и когда нужно получить новый ID - исполнять подобную процедуру.
Вопрос в том, а всегда ли нужен такой танец с бубном или можно обходится без него


 
Курдль ©   (2004-05-14 13:53) [20]

А такая фишка в MSSQL-е не проходит:
select GET_IDENTITY("имя таблицы") as NEW_ID from DUMMY?


 
paul_k ©   (2004-05-14 13:59) [21]

Если верить хелпу GET_IDENTITY в МсСкул не известна


 
Курдль ©   (2004-05-14 14:00) [22]

А есть на чем проверить? Просто по аналогии с Sybase. Вдруг MS SQL это от нее тоже уеаследовал?


 
Skyle ©   (2004-05-14 14:08) [23]


> А есть на чем проверить? Просто по аналогии с Sybase. Вдруг
> MS SQL это от нее тоже уеаследовал?


Нет, такого нет.
А какую задачу решаем? Если хочется просто найти следующее_значение_на_момент_запроса, то это можно сделать и выборкой.
Но в случае многопользовательской работы это нифига не спасёт.

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


 
Курдль ©   (2004-05-14 14:18) [24]

Чаще всего такие вопросы возникают при необходимости получить значение нового идентификатора заранее. Например для того, чтобы сформировать пакет записей для связанных по этому идентификатору таблиц. Не знаю, как в MSSQL, но для 3х СУБД это так:

Sybase: select GET_IDENTITY("имя таблицы") as NEW_ID from DUMMY
Oracle: select имя_последовательности.NEXTVAL NEW_ID from DUAL
InterBase: select GEN_ID("имя таблицы", 1) from rdb$database


 
paul_k ©   (2004-05-14 14:20) [25]

кстати о Sybase
Sybase ASE 12
"GET_IDENTITY" is not a recognized built-in function name.


 
Курдль ©   (2004-05-14 14:23) [26]

Да? На ASA 8.1 уже есть!
Adaptive Server Anywhere SQL Reference Manual
 3. SQL Functions
   Alphabetical list of functions

GET_IDENTITY function [Miscellaneous]

--------------------------------------------------------------------------------

Function
Allocates values to an autoincrement column. This is an alternative to using autoincrement to generate numbers.

Syntax
GET_IDENTITY ( [ owner.] table-name [, num_to_alloc ],... )


 
Skyle ©   (2004-05-14 14:25) [27]

Я не знаю задачи, для которой нужно заранее знать значение первичного ключа.


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

Это можно сделать иначе и совсем несложно...


 
paul_k ©   (2004-05-14 14:29) [28]

2Курдль
Да догадался потом я что Вы на ASA работаете..
Только я Вот вижу Sybase  и сразу почемуто в любимый ASE (Adaptive Server Enterprise) проверять лезу. А там - обшибка синтаксиса..


 
Курдль ©   (2004-05-14 14:30) [29]


> Это можно сделать иначе и совсем несложно...

Можно конкретнее?
Если у меня есть форма с 4-мя ДатаСэтами, ну например, "субъекты" и я ввожу нового физ.лица:
1. Заполняю ФИО (таблица "Субъекты")
2. Ввожу адрес (таблица "Адреса")
3. Ввожу телефон (таблица "Телефоны")
4. Ввожу счет в банке (таблица "Счета")
Причем все записи во всех таблицах новые, а таблицы 2-4 связаны с 1 по первичному ключу?


 
Курдль ©   (2004-05-14 14:33) [30]


> Только я Вот вижу Sybase  и сразу почемуто в любимый ASE
> (Adaptive Server Enterprise) проверять лезу. А там - обшибка
> синтаксиса..

ASA тоже очень быстро прогрессировала, посмотрите и Вы апгрэйды.
В 8.0 еще этого не было, а в 8.1 не было UUID., появилось только в 8.2 (и все за год-два).
Но я не вижу смысла в ASE, не лучше ли сразу на Оракл садиться?


 
bushmen ©   (2004-05-14 14:34) [31]

Если Вы работаете на MS SQL 2000, то проще всего загнать все данные в хранимую процедуру, а там через SCOPE_IDENTITY() получить номер identity-поля.


 
Курдль ©   (2004-05-14 14:39) [32]


> Если Вы работаете на MS SQL 2000, то проще всего загнать
> все данные в хранимую процедуру, а там через SCOPE_IDENTITY()
> получить номер identity-поля.

Возможно я поэтому на нем и не работаю. Для задачи [29] я просто беру значение первичного (для 1) /внешнего (для 2-4) ключа способом [24] (поправить ошибку в конце - не имя_таблицы, а имя_генератора) и прописываю, куда надо.


 
Skyle ©   (2004-05-14 14:41) [33]


> Можно конкретнее?
> Если у меня есть форма с 4-мя ДатаСэтами, ну например, "субъекты"
> и я ввожу нового физ.лица

А если вот так?
Отправляешь запрос такого вида:
BEGIN TRAN
 DECLARE @Id INT

 INSERT FirstTable(....)
 VALUES(.....)

 SELECT @Id = @@IDENTITY

 --А дальше вставка всего остального с использованием @Id.
 -- Это замечательно работает в случае динамического формирования запроса.


 
paul_k ©   (2004-05-14 14:41) [34]

Курдль ©   (14.05.04 14:33) [30]
не будем спорить на что, ни за что садится. Все от задачи пляшет.

Курдль ©   (14.05.04 14:30) [29]
а зачем заранее? достаточно добавить все в правильной последовательности и взять @@identity после каждого инсерта.
тогда и танцы с бубном отплясывать вокруг таблиц не надо.
Тем более когда нужно всего лишь расставить связи и дальше пользовать эти поля для сортировки не предвидится, то мое мнение - uniqueidentifier с NewId() в качестве defaultValue вполне подходит


 
bushmen ©   (2004-05-14 14:42) [35]

>Возможно я поэтому на нем и не работаю

Мало ли что кто делает вообше - вопрос был задан конкретно про MS SQL 2000. А о Ваших личных предпочтениях я осведомился в Вашем вчерашнем посте по поводу транзакций.


 
Курдль ©   (2004-05-14 14:45) [36]


> SELECT @Id = @@IDENTITY

А это к какой таблице(полю/генератору/последовательности)относится?


 
Skyle ©   (2004-05-14 14:47) [37]

After an INSERT, SELECT INTO, or bulk copy statement completes, @@IDENTITY contains the last identity value generated by the statement. If the statement did not affect any tables with identity columns, @@IDENTITY returns NULL.
К последней, которую трогали.


 
bushmen ©   (2004-05-14 14:49) [38]

>А это к какой таблице(полю/генератору/последовательности)относится?

Если Вам это интересно, то на www.sql.ru обсуждался этот вопрос.


 
Курдль ©   (2004-05-14 14:49) [39]

Понял, не дурак! :)))
Но это значит, что надо насильственно открывать транзакцию + все вытекающие...


 
Курдль ©   (2004-05-14 14:54) [40]


> Если Вам это интересно, то на www.sql.ru обсуждался этот
> вопрос.

Да я так - чисто умозрительно! А мало ли где этот вопрос обсуждался?! Я Вас уверяю, что даже на этом форуме все вопросы где-нибудь да обсуждались!
Так что мы имеем? Иначе, чем специально обученной процедурой, идентити из MSSQL не вытянуть?



Страницы: 1 2 вся ветка

Форум: "Базы";
Текущий архив: 2004.06.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.041 c
3-1084869152
It
2004-05-18 12:32
2004.06.06
Редактирование наборов данных в БД через Internet Explorer


14-1085119817
Nick-From
2004-05-21 10:10
2004.06.06
Считывание из файла


3-1084474305
Dmitry Vyacheslavovich
2004-05-13 22:51
2004.06.06
проблема с редактированием связанной таблицы


1-1085384535
i2e
2004-05-24 11:42
2004.06.06
Надо разложить строку "1,4,6-8,15,22"


3-1084525896
ZiaTron
2004-05-14 13:11
2004.06.06
EDBEngineError with Message : Unknow database





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский