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

Вниз

ADO   Найти похожие ветки 

 
CB   (2003-04-24 06:50) [0]

Помогите разобратся.
Заношу данные в таблицы с помощью StoredProcedure(передаю, как параметры) c уникальным ИД. ИД я считываю select max(id) from glavn. Проблема в том, что не могу занести в базу сразу несколько записей(несколько образований, или много родни) т.к. не известен ИД с главной таблицы.
З.Ы. Живу с редким Инетом, если кто-то разрабатывал самостоятельно проекты напишите на мыло, а то есть много мелких вопросов.


 
CB   (2003-04-24 06:56) [1]

Программировать начал только недавно. Так-что не ругайте.


 
NAlexey   (2003-04-24 08:29) [2]

>Проблема в том, что не могу занести в базу сразу несколько записей т.к. не известен ИД с главной таблицы.
Ну если я правильно понял проблему, то после вставки каждой записи, в теле процедуры делай также SELECT MAX(ID) FROM glavn. Что собственно мешает?


 
BoxTer   (2003-04-24 09:03) [3]

ваще MSSQL имеется весьма полезная функция @@identity - которая врзвращает идентификатор последней добавленной записи.
Согласен с NAlexey, но попробуй с @@identity.


 
АлексейК   (2003-04-24 09:16) [4]

При сетевой работе max(id) может быть и не тот который нужен. Тогда логичнее:
SELECT ID FROM TB WHERE ID = @@IDENTITY


 
NAlexey   (2003-04-24 09:46) [5]

>ваще MSSQL имеется весьма полезная функция @@identity
Логично, но автор не сказал что у него там PrimaryKey, так что никакого @@IDENTITY там может и не быть...


 
Orlan Master   (2003-04-24 10:16) [6]

Для MSSQL, таблица с отстутствующим PrimaryKey не имеет права на существование. Во вторых, если PK будет, а на таблицу навешены триггера - вы получите неверный @@identity. Если работаете с MSSQL 2K - то необходимо использовать функцию SCOPE_IDENTITY или IDENT_CURRENT. Вариант SELECT max(id) при сетевой работе имеет смысл если обработка данных происходит в выделенной транзакции. В этом случае гарантированно получается достоверный MAX(ID), ибо пока транзакция не завершена, никто не сможет в нее влезть. Исключение представляет только вариант изоляции транзакции READ UNCOMMITED. Поэтому выделенная транзакция использующая MAX(ID) должна использовать уровень изоляции транзакции отличный от READ UNCOMMITED. Много хлопот, правда? Посему лучше наличие PK в таблице и использование SCOPE_IDENTITY или IDENT_CURRENT.


 
NAlexey   (2003-04-24 10:33) [7]

>Для MSSQL, таблица с отстутствующим PrimaryKey не имеет права на существование
Опять же это предпочтение вкуса. Оспаривать то что ключи использовать выгодно и во многом облегчает дело я не буду, это ясно, но то что таблица с отсутсвующим PK имеет право на существование это факт.

>Вариант SELECT max(id) при сетевой работе имеет смысл если обработка данных происходит в выделенной транзакции. В этом случае гарантированно получается достоверный MAX(ID), ибо пока транзакция не завершена, никто не сможет в нее влезть
А если вариант таков: у меня табличка, которая хранит максимальные ID для различных таблиц. Пусть меняет кто хочет и когда захочет, обратившись к ней в любое время, я получу реальный Max(ID) для той таблицы которая мне нужна.


 
Orlan Master   (2003-04-24 10:43) [8]

>А если вариант таков: у меня табличка, которая хранит максимальные ID для различных таблиц. Пусть меняет кто хочет и когда захочет, обратившись к ней в любое время, я получу реальный Max(ID) для той таблицы которая мне нужна.
Такой вариант от лукавого. Есть неписанное правило: никто не может менять PK таблицы. Если такое допустить - уплывет целостность базы. Смысл делать доп. сущность с коллекцией max_id других сущностей? Перегруз базы лишней инфой. Не достовернее ли сразу получить id через Scope_identity?



 
Johnmen   (2003-04-24 10:45) [9]

>Orlan Master (24.04.03 10:16)

Причем здесь тр-ии и их уровень изоляции - непонятно...

>NAlexey © (24.04.03 10:33)
>А если вариант таков:...

Ни один вариант с MAX(ID) корректно не будет работать в многопользовательской системе.



 
NAlexey   (2003-04-24 10:45) [10]

>Не достовернее ли сразу получить id через Scope_identity?
Достовернее, но у каждого в голове свои тараканы.


 
NAlexey   (2003-04-24 10:47) [11]

>Ни один вариант с MAX(ID) корректно не будет работать в многопользовательской системе.
Почему не будет? Очень даже будет.


 
Orlan Master   (2003-04-24 10:53) [12]

>Почему не будет? Очень даже будет.
Согласен, будет. Если с конкретными данными работаете только вы сами, а система многопользовательская. Подобное решение характерно для разработчика переходящего с локальных БД к серверным, в стадии постижения истин серверных нюансов построения БД. А не надежнее делать не исключительные варианты, а варианты на все случаи жизни? Ведь select max(id) - это до первого попадалова. Я уже хватил подобного на MSSQL7, когда там не было Scope_identity. После этого зарекся.


 
Johnmen   (2003-04-24 10:54) [13]

>NAlexey © (24.04.03 10:47)

Приведи конкретную последовательность действий, которая, как ты думаешь, приведет к "Очень даже будет".


 
СВ   (2003-04-25 08:24) [14]

Добавляю так

insert into table1(11,22) values (@1,@2)
set @n=(select max(id) from glavn)

insert into table2(id1,22) values (@n,@3)

ID - автоинкрементное поле в главной базе(table1).
Программа ~ на 11 юзеров.
Но как добавить несколько записей через DBGrid в table3(несколько дипломов, или родни(table4)), если я не знаю ID.
Хочется без временных таблиц.


 
ЮЮ   (2003-04-25 09:25) [15]

>Ни один вариант с MAX(ID) корректно не будет работать в многопользовательской системе.

А этот работает. Естественно, по ID построен первичный ключ, но он не "автоинкремент".

try
NotRepeat := not [запрос на вставку];
repeat
try
[запросить последний ID]
[выполнить запрос на вставку]
NotRepeat := true;
except
// ошибка при сохранении
if
[пытались вставить] и [запросить последний ID и он вырос]
//значит сохранился кто-то другой
then
устанавливаем новое значение ID
else
raise; // ошибка не в инкременте
end;
until NotRepeat
except
// ошибка не из-за инкремента
end;

>Но как добавить несколько записей через DBGrid в table3(несколько дипломов, или родни(table4)), если я не знаю ID.

Но запись в главную ты уже добавил, она уже имеет ID, им и пользуйся

>Добавляю так
>insert into table1(11,22) values (@1,@2)
> set @n=(select max(id) from glavn)
>insert into table2(id1,22) values (@n,@3)

И где это ты так добавляешь? Сразу два Inserta в две разные таблицы? И при этом ещё и через DBGrid?




 
АлексейК   (2003-04-25 11:01) [16]

Никто и неговорил что SELECT Max(ID) не будет работать. Работать то он будет, и при 11 пользователях вероятность ошибки невелика, однако существует явная вероятность ошибки. Что касается полного блокирования таблицы на время выполнения транцакции, тогда это уже не многопользовательская работа. Хотя в приципе самое простое решение.


 
Johnmen   (2003-04-25 11:10) [17]

>ЮЮ © (25.04.03 09:25)
>А этот работает

Ну да, работает. Только возникающую некорректность ты обрабатываешь...:)


 
АлексейК   (2003-04-25 11:13) [18]

Что же касается какую функцию использовать (Identity, scope_identity, ident_current)
То лучше всего на этот вопрос отвечает документация.

@@IDENTITY
Returns the last-inserted identity value generated in any table in the current session.

IDENT_CURRENT
Returns the last identity value generated for a specified table in any session and any scope

SCOPE_IDENTITY
Returns the last IDENTITY value inserted into an IDENTITY column in the same scope. A scope is a module -- a stored procedure, trigger, function, or batch. Thus, two statements are in the same scope if they are in the same stored procedure, function, or batch.

Следовательно не факт, что @@Inentity, даже если присутствут триггер будет выдавать неправильное значение.




 
NAlexey   (2003-04-25 11:23) [19]


For example, you have two tables, T1 and T2, and an INSERT trigger defined on T1. When a row is inserted to T1, the trigger fires and inserts a row in T2. This scenario illustrates two scopes: the insert on T1, and the insert on T2 as a result of the trigger.

Assuming that both T1 and T2 have IDENTITY columns, @@IDENTITY and SCOPE_IDENTITY will return different values at the end of an INSERT statement on T1.

@@IDENTITY will return the last IDENTITY column value inserted across any scope in the current session, which is the value inserted in T2.


 
АлексейК   (2003-04-25 11:40) [20]

Ну далеко не всегда в триггере надо делать вставки в другую таблицу.


 
Tundra   (2003-04-25 11:47) [21]

А если такой вариант - имеется таблица номеров N1 пользователей подключенных на данный момент к базе - ну скажем от 01 до 99.

А Id можно формировать так :
N1-номер пользователя
Id - (max(id) div 100)*100 + 100 +N1
т.е последние 2 цифры Id соот-ют номеру пользователя.

Тогда точно что не будет проблем - и если еще max(id) выбирать только те Id которые соот-ют номеру пользователя.


 
АлексейК   (2003-04-25 13:15) [22]

Да так делали в Fox"е например. Однако в MSSQL это может делать сервер, то есть отслеживать последний вставленный индефекатор либо для конкретной таблицы, либо текущей сессии, либо в текущей сесии и текущем модуле (XP, Trigger). Ну что еще надо для жизни?



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

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

Наверх





Память: 0.5 MB
Время: 0.008 c
3-59604
Анатолий
2003-04-28 15:06
2003.05.19
Как изменить тип поля в таблице(Currency на Float)?


3-59554
ki11er
2003-04-25 17:28
2003.05.19
Вопрос про PDOXUSRS.NET


14-59872
Snap
2003-04-28 12:37
2003.05.19
Помогите, Линукс не ставится


3-59579
kaon
2003-04-26 15:06
2003.05.19
Scrolling в DBVomboBox e


1-59672
Patrick
2003-05-07 10:42
2003.05.19
Кодировка клавиш





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский