Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Обновление и добавление записи одной конструкцией на MySQL возможно?

279
07 апреля 2009 года
bave
456 / / 07.03.2004
СУБД MySQL
таблицы InnoDB

1. нужно сделать следующее - попытаться добавить запись, если вдруг есть совпадения с каким-нибудь уникальным полем, то вместо добавления выполнить обновление записи, причём сделать это надо как-то наиболее оптимально в одной конструкции...

Replace не предлагать - replace вобще не вариант по понятным причинам...
-----------------------
2. Если решений реализовать п1. в мускуле нет - тогда другой вопрос:
Если использовать insert ignore into... - как узнать выполнился insert или insert был проигнорен? (При этом желательно не делая никаких отдельных селектов на получение максимального значения Id записи до и после инсерта).
285
07 апреля 2009 года
Romik
479 / / 24.11.2002
Используйте ON DUPLICATE KEY UPDATE в конструкции INSERT:
[highlight=sql]
INSERT
`Table` (`id`,`field`)
VALUES (1,'Text')
ON DUPLICATE KEY UPDATE `Table`
SET
`Text`='NewText'
WHERE
`id`=1


[/highlight]
279
09 апреля 2009 года
bave
456 / / 07.03.2004
Тоже не очень походит - on duplicate key не работает в конструкции
 
Код:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...


И в MySQl ещё ко всему процчему нету вообще конструкции update-а из select-а... :(

Вообще всё больше складывается впечатление, что на этой СУБД можно только для детсадовских приложений писать :(
------------------
Судя по всему актуальным становится вопрос 2.
285
09 апреля 2009 года
Romik
479 / / 24.11.2002
ну а если выполнить задачу в 2 этапа? Для начала создать VIEW и заполнить его результатом SELECT, в условии которого будет указано, не выбирать существующие записи в целевой таблице. Вторым этапом заполнить целевую таблицу из VIEW?
285
09 апреля 2009 года
Romik
479 / / 24.11.2002
Впрочем погорячился я со VIEW, достаточно просто в INSERT ... SELECT в условии выборки SELECT исключать имеющиеся записи в целевой таблице
6
09 апреля 2009 года
George
4.1K / / 05.01.2007
у нас делается что то подобное. реализовывали так: копируются данные во временную таблицу. затем данные из временной таблицы сравниваются с данными в таблице назначения. при совпадении записей полностью, напротив соответствующих во временной таблице ставится флаг, типа set flag = '***', где флаг - это поле. при совпадении уникальных полей то же самое, только во флаг записывается ID записи из таблицы назначения. а при полном несовпадении ничего не ставится. а потом делаются Update'ы и инсерты в зависимости от поля flag. это возможно, громоздкое решение, но у нас так.
279
14 апреля 2009 года
bave
456 / / 07.03.2004
у меня сейчас итак через insert... select работает:
Код:
insert ignore into Passport
    (
    Id
    , PassportOwnerId
    , PassportRegistrationAddressId
    , Name
    , Surname
    , PatronymicName
    , PassportSeria
    , PassportNumber
    , PassportOffice
    , PassportDate
    , WhenAdd
    )
  select
    passport.Id
    , passport_composes.PassportOwnerId
    , passport_composes.PassportRegistrationAddressId
    , passport_composes.PersonName
    , passport_composes.PersonSurname
    , passport_composes.PersonPatronymicName
    , passport_composes.PassportSeria
    , passport_composes.PassportNumber
    , passport_composes.PassportOffice
    , passport_composes.PassportDate
    , case when passport.WhenAdd is null then now()
        else passport.WhenAdd
    end
  from
    (select
      person_id PassportOwnerId
      , address.Id PassportRegistrationAddressId
      , person_name PersonName
      , person_surname PersonSurname
      , person_patronymic_name PersonPatronymicName
      , passport_seria PassportSeria
      , passport_number PassportNumber
      , passport_office PassportOffice
      , passport_date PassportDate
    from
      (select
        passport_city_id CityId
        , passport_street_name StreetName
        , passport_house_number HouseNumber) as address_composes
        left join Address address
          on address_composes.CityId = address.CityId
            and address_composes.StreetName = address.StreetName
            and address_composes.HouseNumber = address.HouseAndBlockNumber) as passport_composes
    left join Passport passport
      on passport.PassportOwnerId = passport_composes.PassportOwnerId
  where
    passport_composes.PassportRegistrationAddressId is not null
      and (not exists(
        select
          1
        from
          vwPassport vw_passport
        where
          vw_passport.PassportSeria = passport_composes.PassportSeria
            and vw_passport.PassportNumber = passport_composes.PassportNumber)
        or passport.Id is not null);


Тока мне кроме этого нужно ещё Update сделать,в том случае если запись не добавилась из-за ограничения уникального ключа PassportOwnerId - только вот UPDATE-а из селекта нефига нету :(
И как всётаки узнать выполнился insert или проигнорился - это ведь наверно как-то можно...
279
17 апреля 2009 года
bave
456 / / 07.03.2004
А-а-а-а!!! Всё сделал!!! Работает!!!
На самом деле on duplicate key очень рульная конструкция и с insert ... select она тоже работает, только оноа не многа не такая как писал Romik - не надо ни таблицу указывать, ни условие where - обновляются сразу поля той записи из-за котрой инсерт не удался.
Вообще сделал вот так и запахало как надо:

Фрагмент запроса:
Код:
insert into Passport
    (
    Id
    , PassportOwnerId
    , PassportRegistrationAddressId
    , Name
    , Surname
    , PatronymicName
    , PassportSeria
    , PassportNumber
    , PassportOffice
    , PassportDate
    , WhenAdd
    )
  select
    ....
  from
    ...
  where
    passport_composes.PassportRegistrationAddressId is not null
      and (not exists(
        select
          1
        from
          vwPassport vw_passport
        where
          vw_passport.PassportSeria = passport_composes.PassportSeria
            and vw_passport.PassportNumber = passport_composes.PassportNumber)
        or passport.Id is not null)
   on duplicate key update
      PassportRegistrationAddressId = passport_composes.PassportRegistrationAddressId
      , Name = passport_composes.PassportName
      , Suranme = passport_composes.PassportSurname
      , ... ;


Запросы с on duplicate key такие компактные получаются на них даже смотреть приятно становится :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог