powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Обработчик вставки UNIQUE значений
12 сообщений из 12, страница 1 из 1
Обработчик вставки UNIQUE значений
    #34132391
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В таблице группа полей обозначена как UNIQUE. Естественно, при вставке строк с таким же набором полей вставка не происходит. Меня это не устраивает, нужно чтобы в строке с тем же набором полей в данном случае инкрементировался счетчик. Как это можно реализовать без триггеров и вообще только средствами SQL?
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34132413
Poligon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Первое, что приходит на ум (если без тригеров) :
1) select'ом перед вставкой проверяшь есть ли такой набор
2) если есть увеличиваешь счетчик у нужной строки
3) если нет вставляешь новую строку
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34133605
ZemA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В хранимой процедуре делаем update(увеличиваем счетчик) с условием по уникальным полям
Проверяем если не изменено ни одной строки делаем insert
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
...
update table set counter=counter+ 1  where field=$ 1  and field2=$ 2 ;

if not found then
  insert into table (field, field2, counter) values ($ 1 , $ 2 ,  1 );
end if;
...
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34134193
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ясно. Теперь то же самое, но из клиента на С.

авторwsprintf(lpOut, "INSERT INTO lrtes_log VALUES (%s)", lpEscStr);
res = PQexec(conn, lpOut);
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34134209
Robert Ayrapetyan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
где pEscStr формируется динамически. Где поместить обработчик, если вставка не произошла по причине UNIQUE полей?
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34134515
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сделать аналогично ZemA's варианту
Код: plaintext
1.
2.
3.
4.
res = PQexec(conn, "update...");
if(PQcmdTuples(res) =  0 ) {
  res = PQexec(conn, "insert...");
}
либо же ловить ошибку
Код: plaintext
1.
2.
3.
4.
res = PQexec(conn, "insert...");
if(PQerrorMessage(conn)  != "") {
  res = PQexec(conn, "update...");
}
гдето так, лучший путь - попробовать
PS. может лучше юзать PQexecParams() ?
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34134655
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
оба варианта стремные,
первый потому что во время выполнения if(PQcmdTuples(res) = 0)
может уйти запрос res = PQexec(conn, "update..."); от точно такогоже процеса... соотвественно последний упадет с ошибкой наруения uniq.
спасет лок на таблицу целиком перед апдейтом но это не стандартный скуэль.. вроде.

второй способ стремный потому как если придется выискивать конкретную ошибку о том что конкретно
UNIQ сломался.. кто-то дает гарантии что текс месаги не поменяется и никто локаль не сменит?
и есть еще один минус.. если это все в большой транзакции идет то она обламается ..
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34134692
.gc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
.gc
Гость
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
// from errcodes-appendix.html : 
#define  SQL_STATE_UNIQUE_VIOLATION  "23505"

   PQexec(conn, "SAVEPOINT bla");
   res = PQexec(conn, "INSERT ...");
   if(PGRES_COMMAND_OK != PQresultStatus(res) ) {
     sql_state = PQresultErrorField(res, PG_DIAG_SQLSTATE);
     if(  0  == strcmp(sql_state, SQL_STATE_UNIQUE_VIOLATION) ) {
        PQexec(conn, "ROLLBACK TO SAVEPOINT bla");
        res = PQexec(conn, "UPDATE ...");
     } else {
       // die ...
     }
   } else {
     PQexec(conn, "RELEASE SAVEPOINT bla");
   }
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34138266
ZemA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да епрст
ZemAВ хранимой процедуре делаем update(увеличиваем счетчик) с условием по уникальным полям
Проверяем если не изменено ни одной строки делаем insert

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create function change_counter(text, text) returns void 
    as '
begin
  update table set counter=counter+1 where field=$1 and field2=$2;

  if not found then
    insert into table (field, field2, counter) values ($1, $2, 1);
  end if;

  return;
end;
' language plpgsql;
Код: plaintext
1.
2.
3.
  . . .
  res = PQexec(conn, "select change_counter(...");
  . . .
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34139397
Jelis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ZemA
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create function change_counter(text, text) returns void 
    as '
begin
  update table set counter=counter+1 where field=$1 and field2=$2;

  if not found then
    insert into table (field, field2, counter) values ($1, $2, 1);
  end if;

  return;
end;
' language plpgsql;

Тока тут есть проблеммка, правда больше теоретическая (хотя на сколько она станет практической, зависит от нагрузки на сервер) :
если две транзакции начнуться одновременно (вернее даже, если во время выполнения этой функции запуститься еще одна), у вас в таблице, после обеих коммитов появиться две строки со значением counter = 1 !!! И если у нас стоит uniq то та транзакция что закончиться последней - выдаст ошибку и не сработает!
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34146873
BlackDan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если проверка уникальности полей сделана через индекс, то можно пропробовать всё реализовать через хранимую процедуру.
Вот прототип функции.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
...
DECLARE
  _field1Value ALIAS FOR $ 1 ; 
BEGIN
  ...
  BEGIN
    INSERT INTO table_name(counter, field1)  VALUES( 1 , _field1Value);
  EXCEPTION
    WHEN unique_violation THEN
      IF position('index_name' in SQLERRM) >  0  THEN
        -- Произошел эксепшн по нашему индексу, надо увеличить счетчик
        UPDATE table_name SET counter = counter +  1  WHERE field1 = _field1Value;
      END IF;
  END;
  ...
END

автор=wbearвторой способ стремный потому как если придется выискивать конкретную ошибку о том что конкретно
UNIQ сломался.. кто-то дает гарантии что текс месаги не поменяется и никто локаль не сменит?
и есть еще один минус.. если это все в большой транзакции идет то она обламается ..

в вышеприведенном случае транзакция не обломается. Единственно узкое место тут - это получение информации, что именно по требуемому индексу произошло исключение.
...
Рейтинг: 0 / 0
Обработчик вставки UNIQUE значений
    #34161372
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
первый пост внимательно читали?

Robert Ayrapetyan
Как это можно реализовать без триггеров и вообще только средствами SQL?
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Обработчик вставки UNIQUE значений
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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