powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вопрос по синтаксису Update
25 сообщений из 112, страница 1 из 5
Вопрос по синтаксису Update
    #39909728
Zulus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброе утро, коллеги!
Помогите пожалуйста развеять сомнения.

Есть такой прекрасный код

Код: 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.
use tempdb
go

if object_id('Repayments', 'U') is not null
 drop table Repayments;

create table dbo.Repayments
(
  AppCode       nvarchar(60) not null
, RepaymentDate	smalldatetime not null
, DocNumber     int not null
)
create clustered index cx_Repayments on dbo.Repayments(AppCode, RepaymentDate)
go

declare
  @Part		varchar(120)
, @DocNumber	int
	
set @Part = ''
set @DocNumber = 1

update t set
  @DocNumber = DocNumber = 
	case 
		when @Part <> AppCode then 1
		else @DocNumber + 1
	end
, @Part = AppCode
from dbo.Repayments t



1. Правильно ли я понимаю, что товарищ хочет получить последовательную нумерацию DocNum в пределах AppCode? Может ещё что-то?
2. Можно ли такую конструкцию считать безопасной для условий
- update без where
- один единственный кластерный индекс как указано в схеме
Или есть у такого синтаксиса "подводные камни"?

Код не мой, думаю "бодаться" с партнёрами из-за него или пусть остаётся..
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909737
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zulus
Правильно ли я понимаю, что товарищ хочет получить последовательную нумерацию DocNum в пределах AppCode? Может ещё что-то?
Да.
Zulus
Можно ли такую конструкцию считать безопасной для условий
- update без where
- один единственный кластерный индекс как указано в схеме
Можно. На текущий момент.
Но никто не гарантирует, что будет можно после очередного SP, CU или в новой версии.

Мое имхо - лучше переписать.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909746
Zulus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm
Мое имхо - лучше переписать.

Вот и моё мнение точно такое-же, но тяжеловато с аргументацией для этого конкретного примера :)
invm, спасибо!
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909750
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zulus
тяжеловато с аргументацией для этого конкретного примера
Данный update предполагает сканирование кластерного индекса.

Сканирование может быть упорядоченное - в порядке ключей индеса, а может быть неупорядоченное - в порядке распределения страниц. Во втором случае, вместо последовательной нумерации может получиться каша.

Насколько я знаю, сейчас неупорядоченное сканирование к update неприменимо. Но будет ли так и далее - никто не знает.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909754
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Zulus,

Создание таблицы

Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE dbo.Repayments
             (AppCode       NVARCHAR(60) NOT NULL
            , RepaymentDate SMALLDATETIME NOT NULL
            , DocNumber     INT NOT NULL
             );
CREATE CLUSTERED INDEX cx_Repayments ON dbo.Repayments(AppCode, RepaymentDate);
GO



Наполнение данными
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
INSERT INTO dbo.Repayments(AppCode      
            , RepaymentDate 
            , DocNumber    )
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'a', GETDATE(), 0 UNION ALL 
SELECT 'b', GETDATE(), 0 UNION ALL 
SELECT 'c', GETDATE(), 0 UNION ALL 
SELECT 'd', GETDATE(), 0 UNION ALL 
SELECT 'e', GETDATE(), 0 UNION ALL 
SELECT 'f', GETDATE(), 0 



Обновление

Код: 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.
DECLARE @Part      VARCHAR(60) = '';

WITH a
     AS (
     SELECT 
            CASE
                WHEN AppCode = @Part THEN 1
                ELSE 0
            END+ROW_NUMBER() OVER(PARTITION BY CASE
                                                   WHEN AppCode = @Part THEN @Part
                                                   ELSE CONVERT(VARCHAR(36), NEWID())
                                               END ORDER BY
                                                           (
                                                            SELECT 
                                                                   1
                                                            )) AS rn
          , DocNumber
     FROM 
          dbo.Repayments)
     UPDATE a
       SET 
           DocNumber = rn;

SELECT 
       *
FROM 
     dbo.Repayments;
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909771
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
Обновление

Код: 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.
DECLARE @Part      VARCHAR(60) = '';

WITH a
     AS (
     SELECT 
            CASE
                WHEN AppCode = @Part THEN 1
                ELSE 0
            END+ROW_NUMBER() OVER(PARTITION BY CASE
                                                   WHEN AppCode = @Part THEN @Part
                                                   ELSE CONVERT(VARCHAR(36), NEWID())
                                               END ORDER BY
                                                           (
                                                            SELECT 
                                                                   1
                                                            )) AS rn
          , DocNumber
     FROM 
          dbo.Repayments)
     UPDATE a
       SET 
           DocNumber = rn;

SELECT 
       *
FROM 
     dbo.Repayments;

Это такое тонкое издевательство над сервером?
Все гораздо банальнее.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with a as
(
 select
  DocNumber, row_number() over (partition by AppCode order by AppCode, RepaymentDate) as n
 from
  dbo.Repayments
)
update a
 set
  DocNumber = n;
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909775
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

авторВсе гораздо банальнее.

Все ещё гораздо более банальнее.

вот код автора

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
declare
  @Part		varchar(120)
, @DocNumber	int
	
set @Part = ''
set @DocNumber = 1

update t set
  @DocNumber = DocNumber = 
	case 
		when @Part <> AppCode then 1
		else @DocNumber + 1
	end
, @Part = AppCode
from dbo.Repayments t

SELECT * FROM dbo.Repayments



вот результат выполнения кода автора (и моего)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
AppCode                                                      RepaymentDate           DocNumber
------------------------------------------------------------ ----------------------- -----------
                                                             2019-12-30 11:58:00     2
                                                             2019-12-30 11:58:00     3
                                                             2019-12-30 11:58:00     4
                                                             2019-12-30 11:58:00     5
                                                             2019-12-30 11:58:00     6
                                                             2019-12-30 11:58:00     7
a                                                            2019-12-30 11:58:00     1
b                                                            2019-12-30 11:58:00     1
c                                                            2019-12-30 11:58:00     1
d                                                            2019-12-30 11:58:00     1
e                                                            2019-12-30 11:58:00     1
f                                                            2019-12-30 11:58:00     1



вот результат выполнения Вашего кода

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
AppCode                                                      RepaymentDate           DocNumber
------------------------------------------------------------ ----------------------- -----------
                                                             2019-12-30 11:58:00     1
                                                             2019-12-30 11:58:00     2
                                                             2019-12-30 11:58:00     3
                                                             2019-12-30 11:58:00     4
                                                             2019-12-30 11:58:00     5
                                                             2019-12-30 11:58:00     6
a                                                            2019-12-30 11:58:00     1
b                                                            2019-12-30 11:58:00     1
c                                                            2019-12-30 11:58:00     1
d                                                            2019-12-30 11:58:00     1
e                                                            2019-12-30 11:58:00     1
f                                                            2019-12-30 11:58:00     1
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909786
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
вот результат выполнения кода автора
Нет. Это результат выполнения кода автора на вашем примере и с вашими начальными значениями переменных.

А чтобы правильно готовить примеры, нужно понять как работает код автора. Тогда монстры, подобные вашему, не потребуются.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909795
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

согласен
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909804
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

Правильно будет так

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DECLARE @Part VARCHAR(60) = '';
WITH a
     AS (
     SELECT 
            CASE
                WHEN AppCode = @Part THEN 1
                ELSE 0
            END
            + ROW_NUMBER() OVER(PARTITION BY AppCode ORDER BY AppCode
                                                            , RepaymentDate) AS rn
          , DocNumber
     FROM 
          dbo.Repayments)
     UPDATE a
       SET 
           DocNumber = rn;



Но,

не могли бы Вы наполнить таблицу данными так, чтобы код автора и Ваш код при выполнении давали одинаковый результат ?
используя все возможные значения для поля AppCode ))) в том числе и '', никаких же ограничений на это поле, кроме NOT NULL - нет ?
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909812
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
не могли бы Вы наполнить таблицу данными так, чтобы код автора и Ваш код при выполнении давали одинаковый результат ?
Вы почему-то решили, что @Part нужно инициализировать первым значением из таблицы. Отсюда все проблемы.
Чтобы исходный код и мой давали одинаковый результат @Part нужно инициализировать значением, которого нет в таблице .
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909815
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

нет, это не я решил, вот код автора

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table dbo.Repayments
(
  AppCode       nvarchar(60) not null
, RepaymentDate	smalldatetime not null
, DocNumber     int not null
)
create clustered index cx_Repayments on dbo.Repayments(AppCode, RepaymentDate)
go

declare
  @Part		varchar(120)
, @DocNumber	int
	
set @Part = ''
set @DocNumber = 1




обратите внимание
авторset @Part = ''
и
авторAppCode nvarchar(60) not null позволяет хранить любые строковые значения отличные от NULL, или я не прав ?

авторЧтобы исходный код и мой давали одинаковый результат @Part нужно инициализировать значением, которого нет в таблице.
Это же не согласуется с определением таблицы и кодом автора ?
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909841
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
нет, это не я решил
Да нет, именно Вы.
Почему-то решили, что если set @Part = '', то и первая строка в таблице должна быть с AppCode = ''

Я же говорю - Вы не разобрались, как работает данный update.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909860
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

Ну как не конструктивно, ну если есть у автора возможный изъян в логике (а может и предусмотренное поведение), почему не говорить о CHECK на поле AppCode, который не позволит вставить '', но сейчас-то в этих условиях я делаю все что позволяет приведённая структура

авторПочему-то решили, что если set @Part = '', то и первая строка в таблице должна быть с AppCode = ''

не я это решил, опять же структура данных, если я сделаю
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
INSERT INTO dbo.Repayments(AppCode      
            , RepaymentDate 
            , DocNumber    )
SELECT 'a', GETDATE(), 0 UNION ALL 
SELECT 'b', GETDATE(), 0 UNION ALL 
SELECT 'c', GETDATE(), 0 UNION ALL 
SELECT 'd', GETDATE(), 0 UNION ALL 
SELECT 'e', GETDATE(), 0 UNION ALL 
SELECT 'f', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 


то все равно строки со значением AppCode = '' будут первыми потому что
Код: sql
1.
create clustered index cx_Repayments on dbo.Repayments(AppCode, RepaymentDate)

(опять же структура)

и снова результат выполнения моего кода будет таким же как и результат работы кода автора, в отличие от представленного третьего варианта

Повторюсь, не конструктивно, хотите доказать свою точку зрения как минимум покажите такой же результат, что и до рефакторинга, с использованием среза данных, параметры которых описаны в структуре таблицы, а не ссылайтесь на условия, которых нет в постановке задачи.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909867
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
все равно строки со значением AppCode = '' будут первым
C каких это пор кластерный индекс гарантирует порядок записей?
Только ORDER BY в запросе!
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909872
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
не я это решил, опять же структура данных, если я сделаю
Решили именно Вы.
У автора типичная задача - пронумеровать строки в разрезе определенного критерия и в определенном порядке.
А не ту, котору придумали Вы - "Записать в DocNumber последовательно возрастающее значение, начиная с 2 для всех AppCode = '', а для остальных AppCode - 1"
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909874
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iap,

Код: 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.
CREATE TABLE dbo.Repayments
             (AppCode       NVARCHAR(60) NOT NULL
            , RepaymentDate SMALLDATETIME NOT NULL
            , DocNumber     INT NOT NULL
             );
CREATE CLUSTERED INDEX cx_Repayments ON dbo.Repayments(AppCode, RepaymentDate);
GO

INSERT INTO dbo.Repayments(AppCode      
            , RepaymentDate 
            , DocNumber    )
SELECT 'a', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'b', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'c', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'd', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'e', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 UNION ALL 
SELECT 'f', GETDATE(), 0 UNION ALL 
SELECT '',  GETDATE(), 0 

SELECT 
       AppCode
     , RepaymentDate
     , DocNumber
FROM 
     dbo.Repayments;



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
AppCode                                                      RepaymentDate           DocNumber
------------------------------------------------------------ ----------------------- -----------
                                                             2019-12-30 14:39:00     0
                                                             2019-12-30 14:39:00     0
                                                             2019-12-30 14:39:00     0
                                                             2019-12-30 14:39:00     0
                                                             2019-12-30 14:39:00     0
                                                             2019-12-30 14:39:00     0
a                                                            2019-12-30 14:39:00     0
b                                                            2019-12-30 14:39:00     0
c                                                            2019-12-30 14:39:00     0
d                                                            2019-12-30 14:39:00     0
e                                                            2019-12-30 14:39:00     0
f                                                            2019-12-30 14:39:00     0



Нет ?
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909879
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Результат, критерий истины только результат, код в студию

Может Вы диагноз неправильно поставили ?

invm
Zulus
Правильно ли я понимаю, что товарищ хочет получить последовательную нумерацию DocNum в пределах AppCode? Может ещё что-то?
Да.
Zulus
Можно ли такую конструкцию считать безопасной для условий
- update без where
- один единственный кластерный индекс как указано в схеме
Можно. На текущий момент.
Но никто не гарантирует, что будет можно после очередного SP, CU или в новой версии.

Мое имхо - лучше переписать.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909914
Zulus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iap, моё почтение!
Согласен с тем, что порядок записей гарантируется order by, но в данном случае других вариантов не вижу:
- кластерный индекс (один единственный)
- параллелизма нет (для текущей версии)

Коллеги, спасибо всем участникам :)
Код не мой - я как раз хочу его переделать, но 100% владелец будет вредничать и задавать много "почему"
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909917
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всех с наступающим НГ !!!
Спасибо за обсуждение !!!
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909918
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
entrypoint
Может Вы диагноз неправильно поставили ?
Возможно. Но мой диагноз гораздо боле правдоподобен, чем Ваш.
entrypoint
Нет ?
В общем случае, нет.
Почему, объяснено тут - 22051347
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909937
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,

Там добавление данных INSERT, а не UPDATE про который вы пишите.

Субъективные выводы, ссылки на самого же себя, а главное, полное игнорирование доводов, нет ни одного довода, который я бы не подкрепил кодом

invm
entrypoint
Может Вы диагноз неправильно поставили ?
Возможно. Но мой диагноз гораздо боле правдоподобен, чем Ваш.
entrypoint
Нет ?
В общем случае, нет.
Почему, объяснено тут - 22051347


как можно написать такое когда приведен довод в виде кода, который можно запустить, покрутить, попробовать.

Может, если у вас нет желания создать массив данных, с которыми бы отработал Ваш код, у Вас есть желание опровергнуть
Код: sql
1.
create clustered index cx_Repayments on dbo.Repayments(AppCode, RepaymentDate)

не на словах, а кодом ?
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909940
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Zulus,

Да, порядок строк только ORDER BY, но в данном случае я говорю о том, что первой в таблице будет любая строка со значением AppCode=''.
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909945
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
кстати дубли с AppCode != '' никто не отменял, так что почему нумеровать
в нелогичном случае нужно именно с двух тоже не понятно
...
Рейтинг: 0 / 0
Вопрос по синтаксису Update
    #39909961
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
nullin,

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

Все доводы моего оппонента в лице invm, основаны на предположениях не подкрепленных ничем - "entrypoint не понимает", "entrypoint не разобрался", "entrypoint ошибается", я же в свою очередь следую только той информации, которая была представлена автором и свои доводы подкрепляю ссылками на структуру базы данных (представленную автором), примерами кода, результатами сравнения.

invm, утверждает что я не могу использовать значение '' для AppCode, но я вижу что структура таблицы мне это не запрещает, это одно из валидных значений этой колонки, я утверждаю что согласно опять же структуре таблицы первыми строками в таблице всегда будут строки со значением AppCode='' независимо от порядка вставки, и.т.д. и.т.п., в ответ я получаю бездоказательные возражения

Это некорректно, непрофессионально, с учетом того, что код представленный invm выдает результат отличный от результата автора.

Код, только код критерий истины
...
Рейтинг: 0 / 0
25 сообщений из 112, страница 1 из 5
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вопрос по синтаксису Update
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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