Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
 Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
Здравствуйте.
Есть жирная таблица с четырьмя полями. Все они добавлены в ключ.
+ Скрипт создания таблицы

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[PartnerAnalogs_test](
	[brand] [nvarchar](50) NOT NULL,
	[article] [nvarchar](50) NOT NULL,
	[a_brand] [nvarchar](50) NOT NULL,
	[a_article] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_PartnerAnalogs_test] PRIMARY KEY CLUSTERED 
(
	[brand] ASC,
	[article] ASC,
	[a_brand] ASC,
	[a_article] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

+ Версия сервера на всякий случай

Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) Aug 22 2017 17:04:49 Copyright (C) 2017 Microsoft Corporation Enterprise Edition (64-bit) on Windows Server 2016 Standard 10.0 <X64> (Build 14393: ) (Hypervisor)

Необходимо изменить значение в одном из полей. При этом, если при изменении подразумевается дублирование, то эту строку, в которой пытаемся изменить, нужно удалить (ведь подразумеваемый набор значений во всех полях уже есть).

Пытаюсь пока делать обычный запрос,
DECLARE @Value NVARCHAR(50);
DECLARE @Zam NVARCHAR(50);
SET @Value = 'YAMATO'; -- что хотим заменить
SET @Zam = 'TOYOTA';   -- на что хотим заменить

UPDATE PartnerAnalogs_test SET PartnerAnalogs_test.brand =@Zam
WHERE PartnerAnalogs_test.brand=@Value

но, как и ожидалось, получаю ошибку:
+ текст ошибки
Violation of PRIMARY KEY constraint 'PK_PartnerAnalogs_test'. Cannot insert duplicate key in object 'dbo.PartnerAnalogs_test'. The duplicate key value is (TOYOTA, 43215-P0100, NISSAN, 43215-52L60).


Возможно ли вообще выполнить это задание? На первый взгляд, оно не относится уж к таким редким, ИМХО...

Пытался смотреть в сторону Merge, но в данном случае не знаю можно ли его использовать.

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

З.Ы. Параллельно стоит задача удалить из полей различные специальные символы и пробелы, но, я так полагаю, что с этой задачей вторая явно пересекается... :)
З.З.Ы. Буду рад любым идеям. Сильно не пинайте по возможности.
Заранее благодарю откликнувшихся...
19 ноя 20, 16:51    [22235523]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 6729
SerPaNik
На первый взгляд, оно не относится уж к таким редким

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

Ключ на все поля - это печально. Не делайте так.

Один из вариантов решения - сгенерите времянку со старым и новым значениями. Потом проверьте "дубли" и удалите их. А оставшимся обновите. Для консистентности - в одной транзакции.
19 ноя 20, 16:59    [22235532]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
Ключ на все поля - это печально. Не делайте так.

Условия уже есть, надо выполнить задачу. Ключи по всем полям, видимо, делали для уникальности значений в каждой строке...

Один из вариантов решения - сгенерите времянку со старым и новым значениями. Потом проверьте "дубли" и удалите их. А оставшимся обновите. Для консистентности - в одной транзакции.

Я извиняюсь, но, если не сложно, можно подробней. Я не силен в скульном диалекте и в SQL тоже. К сожалению, и надеюсь, что пока. :)
19 ноя 20, 17:34    [22235564]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
godsql
Member

Откуда:
Сообщений: 135
SerPaNik,

Если по-простому, то
if exists (select * from T where ...=@new)
then
delete from T where ...=@old
else
update
set ..=@new
where ...=@old

Если по сложному, то merge
19 ноя 20, 17:52    [22235577]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
fkthat
Member

Откуда:
Сообщений: 3894
Я вообще что-то не вкурил. Если ключ по всем полям (допустим их два) и у меня есть запись {"foo", "bar"}, то нужно при добавлении записи {"foo", "bar"} ту запись {"foo", "bar"}, которая уже есть удалить, что ли? Смысл какой?
19 ноя 20, 17:55    [22235579]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
godsql

Если по-простому, то...
Спасибо. Попробую. Но в таблице несколько сотен миллионов записей...
Подозреваю, что будет очень долго.

Если по сложному, то merge
А вот с Merge я пытался, но так у меня ничего и не получилось сделать. Думаю. что этот способ должен быть быстрее на такой жирной таблице...
Был бы рад примерам... Спасибо.
19 ноя 20, 17:57    [22235580]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
invm
Member

Откуда: Москва
Сообщений: 9494
SerPaNik
Был бы рад примерам
with t as
(
 select
  a.brand, b.brand as brand__new
 from
  PartnerAnalogs_test a left join
  PartnerAnalogs_test b on b.brand = @Zam and b.article = a.article and b.a_brand = a.a_brand and b.a_article = a.a_article
 where
  a.brand = @Value
)
merge into t
using (values (@Zam)) s(brand) on 1 = 1
when matched and t.brand__new is null then
 update
  set
   brand = s.brand
when matched and t.brand__new is not null then
 delete;
19 ноя 20, 18:02    [22235590]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
PaulYoung
Member

Откуда: Москва
Сообщений: 2558
SerPaNik
Необходимо изменить значение в одном из полей. При этом, если при изменении подразумевается дублирование, то эту строку, в которой пытаемся изменить, нужно удалить (ведь подразумеваемый набор значений во всех полях уже есть).
Похоже, что нужно просто ничего не делать в этом случае, ведь сами же пишете, что такая запись уже есть в вашей таблице и дублей быть не должно.
19 ноя 20, 18:06    [22235593]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
fkthat
Я вообще что-то не вкурил. Если ключ по всем полям (допустим их два) и у меня есть запись {"foo", "bar"}, то нужно при добавлении записи {"foo", "bar"} ту запись {"foo", "bar"}, которая уже есть удалить, что ли? Смысл какой?

Смысл в изменении. Если есть записи:
brandarticlea_branda_article
MITSUBISHI125MITSUBISHIMD312639
BOSCH0 092 S40 260BOSCH0092S40260
BOSCH0 092 S40 260VARTA5704120633132
BOSCH0 242 129 515CHAMPIONOE201/T10
BOSCH125MITSUBISHIMD312639

И я хочу изменить значения в поле brand с MITSUBISHI на BOSCH, то возникнет ошибка. Ибо изменяемая первая строка будет после изменения идентична последней. В таком случае я хотел, чтобы первая строка была просто удалена ибо результат изменения уже есть в базе...
Как-то так.
19 ноя 20, 18:07    [22235595]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
PaulYoung
SerPaNik
Необходимо изменить значение в одном из полей. При этом, если при изменении подразумевается дублирование, то эту строку, в которой пытаемся изменить, нужно удалить (ведь подразумеваемый набор значений во всех полях уже есть).
Похоже, что нужно просто ничего не делать в этом случае, ведь сами же пишете, что такая запись уже есть в вашей таблице и дублей быть не должно.

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

Сообщение было отредактировано: 19 ноя 20, 18:06
19 ноя 20, 18:09    [22235597]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
PaulYoung
Member

Откуда: Москва
Сообщений: 2558
SerPaNik
PaulYoung
пропущено...
Похоже, что нужно просто ничего не делать в этом случае, ведь сами же пишете, что такая запись уже есть в вашей таблице и дублей быть не должно.

Не запись есть, а такое сочетание значения полей. Но мы же в другой строке меняем, вот ее и удалить...
Если мы меняем в другой строке и результат изменения не валиден, об этом нужно сообщить клиенту и ничего не удалять. А так у вас какая-то странная логика получается.
19 ноя 20, 18:12    [22235602]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47025
Надо добавить нормальное уникальное поле, сделать его первичным ключом, в триггере AFTER UPDATE удалить записи с задублированными полями с не минимальным первичным ключом.
Ведь я могу проапдейтить зараз 100500 записей, после чего получится сто тыщ записей с одинаковыми значениями.
19 ноя 20, 18:26    [22235609]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
invm
Member

Откуда: Москва
Сообщений: 9494
SerPaNik
Не запись есть, а такое сочетание значения полей. Но мы же в другой строке меняем, вот ее и удалить... Ключи ведь по всем полям...
Ответов не читаем?
19 ноя 20, 18:29    [22235615]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
invm
Ответов не читаем?

Конечно читаем. Я просто пока отвечаю на одно, не вижу, что пришел ответ. Ваш проверяю и пытаюсь понять смысл, чтобы разобраться. С учетом моих скудных знаний. :) В любом случае спасибо...
19 ноя 20, 18:33    [22235621]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
PaulYoung, Логика в том, что криво добавили записи из CSV. Поэтому приходиться подчищать. Но это в моем случае.
И в чем плоха логика и изменить на нужные значения поля в строке и при этом избежать дублирования (т.е. ошибок в моем случае с ключами по всем полям)?
При изменении значения, если дубля не предполагается, то изменить, а если дубль после изменения предполагается, то удалить изменяемую, потому что аналогичная уже есть. Вроде логика нормальная...
З.Ы. Это таблица аналогов запчастей. т.е. производитель, артикул, производитель аналога, и артикул аналога. Может эта информация поможет понять, почему я так думал сделать...

Сообщение было отредактировано: 19 ноя 20, 18:34
19 ноя 20, 18:38    [22235627]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
PaulYoung
Member

Откуда: Москва
Сообщений: 2558
SerPaNik,

у вас в CSV "сырые" данные? а каталог запчастей нормализован и хранится отдельно?
19 ноя 20, 18:44    [22235630]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
PaulYoung, я пытаюсь помочь исправить ситуацию на данный момент. В csv прислали данные, которые нужно было загрузить. Корректность их никто не проверял. Так и загрузили. Теперь нужно исправить ситуацию. Но эта инфа ведь не относится к сабжу.
19 ноя 20, 18:52    [22235638]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
invm, Большущее Вам спасибо!
Проверил. То, что нужно!
З.Ы. Тут нет системы плюсиков насколько я понял. Так бы с огромным удовольствием "влепил" бы за помощь! :)
Еще раз спасибо!
19 ноя 20, 19:00    [22235644]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
Не хочу создавать новую тему, но как в моем случае очистить все значения в поле от различных символов? Например, -()*;'@ и т.д.
Операция изменения проходит нормально, спасибо еще раз. А вот какой запустить скрипт, чтобы очистил от этих спецсимволов и пробелов все значения в определенном поле например?
Хорошо бы, если бы множество этих символов можно было задать. Напоминаю, в моем случае составной ключ по всем полям и опять же надо избежать ошибки дублирования...
Забыл сказать спасибо так же godsql за код. Спасибо.
20 ноя 20, 12:52    [22235985]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 6729
SerPaNik,

К сожалению, нормальный translate в sql server не завезли, но можно так.
select replace(translate('G)))@@%&$ood','a!@#$%^&*()','a##########'),'#','') s 
20 ноя 20, 14:04    [22236035]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
iap
Member

Откуда: Москва
Сообщений: 47025
Пример.
#T - таблица со строками, @CharsForErase - строка с символами, которые надо удалить из всех строк.
IF OBJECT_ID(N'tempdb..#T') IS NOT NULL DROP TABLE #T;
GO
CREATE TABLE #T(ID INT NOT NULL IDENTITY, S VARCHAR(100));
INSERT #T(S) VALUES('abcd  @bv453\\'),('xyz@#%^&dfs 54jkhgb'),('павыпа4321!"№(*:%;№');

DECLARE @CharsForErase VARCHAR(100)='# @^';

SELECT ID,
(
 SELECT C FROM
 (
  SELECT TTT.ID,V.number,C=SUBSTRING(TTT.S,V.number,1)
  FROM #T TTT
  JOIN master.dbo.spt_values V ON V.number BETWEEN 1 AND LEN(TTT.S)AND V.type='P'
  WHERE TTT.ID=T.ID
 ) TT
 WHERE @CharsForErase NOT LIKE '%'+TT.C+'%'
 ORDER BY TT.number
 FOR XML PATH(''),TYPE
).value('.','VARCHAR(100)') S
FROM #T T
ORDER BY ID;
Вместо master.dbo.spt_values годится любой источник достаточного количества целых чисел.
20 ноя 20, 15:13    [22236080]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
env, спасибо. попробую проверить :)
20 ноя 20, 16:36    [22236144]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
iap, спасибо, вот тут нужно будет мне больше времени, чтобы понять. А еще как сделать так, чтобы и ошибок на ключ не возникало :)
20 ноя 20, 16:38    [22236145]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
env, Хорошо чистит, еще раз спасибо. :)

Сообщение было отредактировано: 20 ноя 20, 18:01
20 ноя 20, 18:01    [22236175]     Ответить | Цитировать Сообщить модератору
 Re: Составной ключ по всем полям. При Update, если будет дубль, то удалить исходную строку  [new]
SerPaNik
Member

Откуда:
Сообщений: 30
Пытаюсь срастить запрос изменения с обходом ошибки ключа со строкой удаления спецсимоволов.
with t as (select a.brand, b.brand as brand__new from PartnerAnalogs_test a left join PartnerAnalogs_test b on b.brand = a.brand and b.article = a.article and b.a_brand = a.a_brand and b.a_article = a.a_article)
 --where  a.brand = @Value)
merge into t
using (values (replace(translate(brand,'a!''"(@#-$%^&*)} ','a###############'),'#',''))) s(brand) on 1 = 1
when matched and t.brand__new is null then
 update set brand = s.brand
when matched and t.brand__new is not null then delete;

Синтаксис вроде правильный, но выскакивает ошибка при выполнении: "Invalid column name 'brand'"
З.Ы. Напомню. С SQL пока разговариваю на жестах...
20 ноя 20, 18:36    [22236184]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить