![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Функция в MSSQL2000 [D7, XP]
deras © (2008-05-30 01:34:00)Описание. Есть таблица: ID, ContrNum (int), Name
Задача.
Создать функцию, которая возвращает номер контракта (ContrNum = ID + 100000), предварительно проверив, нет ли такого номера контр. в таблице.
Спасибо
ANB (2008-05-30 19:22:00) [1]
> Нумеровать документы вообще и контракты в частности - преррогатива
> того, кто занимается делопроизводством и не целесообразно
> (а часто даже категорически нельзя) вычислять их программно.
>
> Как Ваша система "плюс один" будет работать если, к примеру,
> все документы с нового года нумеруются заново с единицы
> ? А бывает, что в номере документа присутствуют год и даже
> месяц.
> Контракт не вводится сразу в комп, он сначала готовится
> (например, в ворде), потом подписывается, штампуется, регистрируется
> в делопроизводстве. И только после этого вводится "с бумаги"
> как готовый документ в БД
> Очевидно, "тетенька" попросила Вас сделать ей хорошо, не
> представляя себе как это "хорошо" плохо в действительности.
>
Насчет нумерации - согласен, что это более хитрая штука, чем ПК.
Но :
1. Почему запрет на генерацию документов програмно ? Есть продукты, которые целые пакеты документов сами генерят. Для того и предназначены.
2. А уж если в организации документы генерятся автоматизированно, за каким их ручками в журнале нумеровать ? Почему бы не попросить это сделать программу ? А заодно вести и электронный журнал документов.
ЗЫ. Кистате, у нас как раз документы автоматически нумеруются. И мона настраивать период нумерации (т.е. раз в год, месяц, неделю, день начинать с 1)
Ega23 (2008-05-30 18:41:00) [2]
> а, ну... если в плане существования триггеров рассматривать,
> то конечно твоя правда...
Ну реально в данный момент их может и не быть. Но потом бах - и появятся. Так что лучше сразу соломки подстелить...
Palladin (2008-05-30 18:39:00) [3]а, ну... если в плане существования триггеров рассматривать, то конечно твоя правда...
Ega23 (2008-05-30 18:19:00) [4]
> чем?
SCOPE_IDENTITY and @@IDENTITY will return last identity values generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.
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.
SCOPE_IDENTITY() will return the IDENTITY value inserted in T1, which was the last INSERT that occurred in the same scope. The SCOPE_IDENTITY() function will return the NULL value if the function is invoked before any insert statements into an identity column occur in the scope.
И, по-хорошему, надо как-то так делать:
SET NOCOUNT ON;
INSERT INTO ... VALUES....;
SEELECT SCOPE_IDENTITY();
И всё это одним Open вызывать.
А то ты в два захода рискуешь совсем не те данные получить...
Palladin (2008-05-30 17:59:00) [5]
>Ega23 © (30.05.08 14:50) [33]
чем?
Azize (2008-05-30 15:45:00) [6]
> Очевидно, "тетенька" попросила Вас сделать ей хорошо, не
> представляя себе как это "хорошо" плохо в действительности.
>
> мне кажется, что паренёк делает лабу
MsGuns (2008-05-30 15:40:00) [7]Нумеровать документы вообще и контракты в частности - преррогатива того, кто занимается делопроизводством и не целесообразно (а часто даже категорически нельзя) вычислять их программно.
Как Ваша система "плюс один" будет работать если, к примеру, все документы с нового года нумеруются заново с единицы ? А бывает, что в номере документа присутствуют год и даже месяц.
Контракт не вводится сразу в комп, он сначала готовится (например, в ворде), потом подписывается, штампуется, регистрируется в делопроизводстве. И только после этого вводится "с бумаги" как готовый документв БД
Очевидно, "тетенька" попросила Вас сделать ей хорошо, не представляя себе как это "хорошо" плохо в действительности.
Ega23 (2008-05-30 14:50:00) [8]
> q.SQL.Text:='select @@Identity';
лучшеselect scope_identity()
deras (2008-05-30 14:46:00) [9]
> Palladin © (30.05.08 14:32) [30]
> Ega23 © (30.05.08 14:37) [31]
Благодарю!
Ega23 (2008-05-30 14:37:00) [10]
>
> Супер! Вот на этом меня и заклинило :-) А как оказывается
> просто. Надо читать мат часть...
Можно попробовать и функцией ISNULL воспользоваться, типа
SET @NUM = (SELECT ISNULL(IDENT_CURRENT('dbo.Sale'), 1)), но тут я не уверен. В смысле, не знаю, что IDENT_CURRENT при отсутствии записей вернёт - NULL или нет.
Надо смотреть. Первый вариант - более универсальный, второй - ИМХО более правильный. Но надо проверить.
Palladin (2008-05-30 14:32:00) [11]получить... да просто
таблица id(счетчик),name(что нибудь)
Var
q:TADOQuery;
q.SQL.Text:='insert into table (name) values (:PName)';
q.Parameters.ParamByName('PName').Value:='name';
q.ExecSQL;
q.SQL.Text:='select @@Identity';
q.Open;
ShowMessage('NewID:'+q.Fields[0].AsString);
q.Close;
deras (2008-05-30 14:32:00) [12]
> Ega23 © (30.05.08 14:29) [28]
Супер! Вот на этом меня и заклинило :-) А как оказывается просто. Надо читать мат часть...
Спасибо всем за ответы!
Ega23 (2008-05-30 14:29:00) [13]
> Но если запись первая, то @NUM=NULL, что вызывает ошибку.
> Вот я и не знаю, что делать
SET @NUM = (SELECT IDENT_CURRENT('dbo.Sale'))
IF @NUM IS NULL SET @NUM=1
deras (2008-05-30 14:25:00) [14]
> Palladin © (30.05.08 14:16) [26]
согласен... сам виноват...
Palladin (2008-05-30 14:16:00) [15]
> deras (30.05.08 14:10) [25]
а теперь пепречитай свой первый пост. каким пОпом кто-то должен был догадаться, что тебе именно это и нужно? потому и стеб над тобой возник...
deras (2008-05-30 14:10:00) [16]
> Для предварительного хватит и max(id)+1, а id обыкновенный
> счетчик, и реальный номер присвоившийся потом показывается
> после фиксации конктрака
вот это то, что мне и нужно. Если "Для предварительного хватит и max(id)+1" - это реализует вышеописаная ф-ция, то как реализовать "реальный номер присвоившийся потом показывается после фиксации конктрака"?
deras (2008-05-30 14:06:00) [17]
> Azize © (30.05.08 14:01) [22]
так не подойдет ибо надо ф-цией организовать
Я сделал так
CREATE FUNCTION dbo.GetContractNumber ()
RETURNS int
AS
BEGIN
DECLARE @NUM INT
SET @NUM = (SELECT IDENT_CURRENT('dbo.Sale'))
RETURN(@NUM+100000)
END
Но если запись первая, то @NUM=NULL, что вызывает ошибку. Вот я и не знаю, что делать
Palladin (2008-05-30 14:02:00) [18]
> Ega23 © (30.05.08 13:58) [21]
> А он и не должен генериться автоматом на серверной стороне.
Если он естественный ключ, то конечно. Только если сидят 3 деффачки блондики, все 3 открыли форму ввода, а там один и тот же предлагаемый то они долго будут боротся между собой при сохранении и звать аффтора с воплями "программа зависла" :)
А если в качестве номера использовать суррогатный, то почему бы и нет. Только свистопляски с функцией нафик никому не нужны. Для предварительного хватит и max(id)+1, а id обыкновенный счетчик, и реальный номер присвоившийся потом показывается после фиксации конктрака.
Azize (2008-05-30 14:01:00) [19]
> deras (30.05.08 13:55) [19]
Так генерируй ты ID до вывода формы и проверяй
Пример
ID=Random(N);
While Kontrakt.Locate('ID',ID,[]) do ID=Random(N);
CreateForm(....)
Ega23 (2008-05-30 13:58:00) [20]
> это никак не решает проблему с предпросмотром номера незафиксированного
> контракта
А он и не должен генериться автоматом на серверной стороне. Максимум, чего бы я тут сделал - при добавлении нового предложилбы вариант номера (т.е. повесил бы функцию обращения к серверу на Create формы-добавления контракта).
Но это, конечно, ИМХО.