powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Возвращение из пользовательской функции значения по наростающей в Update запрос
21 сообщений из 21, страница 1 из 1
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780542
Объясните пожалуйста в чем затруднение, или подскажите если не трудно другой способ решения задачи:

В поле таблицы необходимо проставить код с контрольной суммой вычисляемой по определенному алгоритму на основании порядкового номера.

Поскольку в колонке изначально значения нет, то порядковый номер беру(возможно ошибочно) из суммы пустых полей этой таблицы:
Код: sql
1.
2.
3.
4.
SELECT count(*)
FROM  table1 t1
where t1.DATEGEN = @date_akt -- месячная выборка
and t1.cod <> 0



Результат этого запроса инкриминирую и помещаю в пользовательскую функцию вместе с алгоритмом расчета:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE FUNCTION get_cod(@head char(8), @date_akt date) -- кроме даты константа для расчета
	RETURNS char(14)
	BEGIN
		declare @used_cod int;
		declare @used_cod_char char(5);
		declare @core char(13);
                ....
		declare @result char(14);
		SET @used_cod = (SELECT count(*) -- место, где считаю сколько уже занесено кодов
			FROM  table1 t1
			where t1.DATEGEN = @date_akt
			and t1.cod <> 0)
		SET @used_cod = @used_cod +1 -- получаю след.номер
		SET @used_cod_char= STUFF('00000',6-(len(@used_cod)),len(@used_cod),RTRIM(LTRIM(CAST(@used_cod AS char))));	-- это маска для №3 будет например 00003
		SET @core= @head + @used_cod_char --- продолжаю собирать контрольную сумму
		SET @noteven = (select CAST(left(@core,1) AS int)
			+ CAST(SUBSTRING(@core,3,1) AS int)
                 .....   --- тело формулы по условию, всякие расчеты по чет/не чет и т.д. 
		SET @result = @core + CAST(@remainder AS char(1)) -- конец вычисления контрольного числа, тоже к теме не имеет отношения
		RETURN @result
END



Прогнав на select-е при пустой колонке cod и при полностью заполненной доп. запросом убеждаюсь что контрольная сумма 1-го и последних чисел верна. Вроде-бы функция написана верно.

Теперь запускаю запрос на заполнение:

Код: sql
1.
2.
3.
4.
Update t1 set t1.cod = dbo.get_cod('77720190228',@dategen)
FROM   dbo.person p
INNER JOIN table1 t1 on (t1.acc = p.c_acc)	 
where p.n_district=2 and t1.DATEGEN = @dategen --  в реальной таблице связей больше, но к теме это не имеет отношения ets.



Запрос отрабатывает на ожидаемом кол-ве строк, но выдает в колонке cod только 1-ю контрольную сумму на всей выборке.
Почему? не сработало!
Подсознательно понимаю... что транзакция update запроса не завершилась до конца все выборки и в поле cod пусто, и функция выгребая кол-во заполненных полей не получает постепенное нарастание т.к. запрос вызвавший ее еще на отработал. Наверно это
самое простое объяснение, но мне как быть, был бы это PHP поставил бы глобальную переменную и черпал бы из нее нарастающую величину. А тут как быть...

Обернул запрос в пару BEGIN TRANSACTION - WAITFOR DELAY '00:00:01.00' -COMMIT TRAN но это ожидаемо не помогло.

Помогите пожалуйста советом малопрактикующему sql-програмисту.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780559
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Прокопенко 8,

Через cross apply вызови, а так бред чистой воды
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780575
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKСергей Прокопенко 8,

Через cross apply вызови, а так бред чистой водыне поможет

ТС, хочет видеть при каждом "следующем" вызове функции в Update , к-во "обновившихся" записей в этом же Update !
Вообщем, там "проце-дурный" подход в самом кондовом его виде :)

ТС,

Будет что-то типа этого
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
;with cte as (
  SELECT 
    t1.*
    ,used_cod = sum(case when t1.cod <> 0 then 1 else 0 end)over()
    ,curr_cod_add = row_number()over(order by case when t1.cod <> 0 then 1 else 0 end)
  FROM   dbo.person p
  INNER JOIN table1 t1 on (t1.acc = p.c_acc)	 
  where p.n_district=2 and t1.DATEGEN = @dategen
)
update cte
set = /* вот тут должна быть вся та "вакханалия", которую ты делаешь в функции. Твой @used_cod (из функции) для каждой записи будет равен used_cod+curr_cod_add */
where t1.cod = 0


Выполни запрос из cte отдельно и посмотри результат, - думаю поймешь идею ...
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780576
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fix
court
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
;with cte as (
  SELECT 
    t1.*
    ,used_cod = sum(case when t1.cod <> 0 then 1 else 0 end)over()
    ,curr_cod_add = row_number()over(order by case when t1.cod <> 0 then 1 else 0 end)
  FROM   dbo.person p
  INNER JOIN table1 t1 on (t1.acc = p.c_acc)	 
  where p.n_district=2 and t1.DATEGEN = @dategen
)
update cte
set cte.cod = /* вот тут должна быть вся та "вакханалия", которую ты делаешь в функции. Твой @used_cod (из функции) для каждой записи будет равен used_cod+curr_cod_add */
where cte.cod = 0
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780628
Спасибо court за помощь.
Я нарушил правило: не брать данные в функции из вне, кроме, как только из параметров функции.
1 шаг, создаю доп.поле cod1
2. обновляю его номером строки через over()
3. update таблицы той же функцией но уже с 3-мя параметрами, где новый - наращенный cod
4. подтираю - удаляю столбец сod1

Хотя можно и через CTE-красивее

Спасибо.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780635
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Прокопенко 8,
авторЯ нарушил правило: не брать данные в функции из вне, кроме, как только из параметров функции.

2 Правило бойцовского клуба?
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780642
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Прокопенко 8Я нарушил правило: не брать данные в функции из вне, кроме, как только из параметров функции.Вы в своем update всего-то нарвались на Halloween Problem.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780646
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmСергей Прокопенко 8Я нарушил правило: не брать данные в функции из вне, кроме, как только из параметров функции.Вы в своем update всего-то нарвались на Halloween Problem.
нет
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780649
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKнетПлан запросите у ТС'а.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780650
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaKнетПлан запросите у ТС'а.
авторSET @used_cod = (SELECT count(*) -- место, где считаю сколько уже занесено кодов
FROM table1 t1
where t1.DATEGEN = @date_akt
and t1.cod <> 0)
это явно не оттуда
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780806
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

https://sqlperformance.com/2013/02/sql-plan/halloween-problem-part-4
Раздел "SCHEMABINDING and T-SQL Scalar Functions"
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780819
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,
вот план его запроса, разве Eager Spool не есть "та защита" от Halloween ?

...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780828
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKinvm,
вот план его запроса, разве Eager Spool не есть "та защита" от Halloween ?


Так там в конце как раз и рассказано, что использование не SCHEMABOUND функции, заставляет предполагать оптимизатор в необходимости защиты, а не сам факт ее необходимости.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780829
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Руслан ДамировичTaPaKinvm,
вот план его запроса, разве Eager Spool не есть "та защита" от Halloween ?


Так там в конце как раз и рассказано, что использование не SCHEMABOUND функции, заставляет предполагать оптимизатор в необходимости защиты, а не сам факт ее необходимости.
и?
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780833
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Руслан Дамирович,

точнее если читать не только поперёк, а ещё и вдоль (как крокодила), то вся суть сводится к
автор Unless a scalar function is declared with the SCHEMABINDING option, SQL Server assumes the function accesses tables.
а тут хоть вдоль хоть поперёк обращение к таблице есть. Что соответчсеввно с доблаением даже SCHEMABINDING в планах ничего не меняет
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780847
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Лично я считаю, что дело в детерминированности, а не в SCHEMABINDING.
В недетерминированной скалярной функции потенциально возможен доступ к данным, поэтому в план добавляется halloween protection.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780849
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmTaPaK,

Лично я считаю, что дело в детерминированности, а не в SCHEMABINDING.
В недетерминированной скалярной функции потенциально возможен доступ к данным, поэтому в план добавляется halloween protection.
так проблема не в Halloween Problem?
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39780869
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaKтак проблема не в Halloween Problem?Решили попридираться к словам?
Ок, дело в защите от Halloween Problem.
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39781138
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court...
Тогда уж так как-то:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
CREATE FUNCTION get_cod( @head CHAR(8), @used_code INT )
RETURNS CHAR(20)
WITH SCHEMABINDING
	BEGIN
		DECLARE
      @char CHAR(12),
		  @core CHAR(20),
      ....
		  @result char(20)
    ;
		SET @char = RIGHT( REPLICATE( '0', 11 ) + CONVERT( VARCHAR(12), @used_code ), 11 );	-- это маска для №3 будет например 00003
		SET @core= @head + @char --- продолжаю собирать контрольную сумму
		SET @noteven = (select CAST(left(@core,1) AS int)
			+ CAST(SUBSTRING(@core,3,1) AS int)
                 .....   --- тело формулы по условию, всякие расчеты по чет/не чет и т.д. 
		SET @result = @core + CAST( @remainder AS char(1) ) -- конец вычисления контрольного числа, тоже к теме не имеет отношения
		RETURN @result
END
;
DECLARE @dategen DATE = GETDATE()
;
WITH 
cte as (
  SELECT 
    t1.[cod],
    [used_code] = row_number()over(order by case when t1.cod = 0 then 1 else 0 end)
  FROM
    dbo.person p
    INNER JOIN table1 t1 on (t1.acc = p.c_acc)	 
  WHERE
    p.n_district=2 and t1.DATEGEN = @dategen
)
UPDATE 
  cte
SET 
  cod = get_cod( '77720190228',[used_code] )
WHERE 
  cod = 0
;


...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39781207
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подозреваю, что автор хотел на самом деле вот это сделать:

Код: sql
1.
2.
declare @val int = 0
update tbl set @val = @val + 1, fn_some_calculation(@val, tbl.field1, tbl.field2)
...
Рейтинг: 0 / 0
Возвращение из пользовательской функции значения по наростающей в Update запрос
    #39781412
Все гениальное просто:

Владислав КолосовПодозреваю, что автор хотел на самом деле вот это сделать:

Код: sql
1.
2.
declare @val int = 0
update tbl set @val = @val + 1, fn_some_calculation(@val, tbl.field1, tbl.field2)


Спасибо, Владислав Колосов

У CTE есть 1н большой минус, коллеги замещающие тебя во время больничного или отпуска решительно не приемлют такую форму записи и норовят впихнуть пароль от TeamViewer-ра.
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Возвращение из пользовательской функции значения по наростающей в Update запрос
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]