powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Обновить ТОЛЬКО ОДНУ запись
23 сообщений из 23, страница 1 из 1
Обновить ТОЛЬКО ОДНУ запись
    #39641778
Perederiy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В таблице есть несколько записей с id=333.
Необходимо обновить только одну из них.
Как это сделать ?
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39641806
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PerederiyВ таблице есть несколько записей с id=333.
Необходимо обновить только одну из них.
Как это сделать ?

Ну например select ctid, * from SOMETABLE where id=333;
и далее обновляем через

update SOMETABLE SET ... WHERE id=333 and ctid=(какой нить из полученных на предыдущем шаге);

это если записи до байта совпадают (тоесть полные копии)
иначе добавляем условие на какое то из полей еще которое у них разное вместо условия на ctid.

--
Maxim Boguk
dataegret.ru
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39641813
Alex URS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
если не важно какую из них - то так:

Код: plsql
1.
2.
3.
4.
5.
6.
UPDATE table
SET ...
FROM (
SELECT * FROM table
where id = 333
ORDER BY id DESC LIMIT 1)
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39641859
ОКТОГЕН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть ещё один грязный способ.
Добавить в таблицу поле с последовательностью по умолчанию.
По этому полю ориентироваться.
Грязный потому, что неоптимально для диска. Сильно неоптимально.
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39641918
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex URSесли не важно какую из них - то так:

Код: plsql
1.
2.
3.
4.
5.
6.
UPDATE table
SET ...
FROM (
SELECT * FROM table
where id = 333
ORDER BY id DESC LIMIT 1)



Какой то бред вы написали... в таком виде оно вам вообще всю таблицу обновит.
Откуда у вас идея что так можно делать?

--
Maxim Boguk
dataegret.ru
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642035
gav21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex URS,

полагаю правильней так
Код: sql
1.
2.
3.
4.
5.
6.
7.
UPDATE table
SET ...
FROM (
SELECT * FROM table
where id = 333
ORDER BY id DESC LIMIT 1) q1
WHERE table.id = q1.id



иначе правда, обновит все
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642037
gav21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gav21,

а нет,лажа, лимит не работает :(
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642213
PgSQLanonymous3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ещё можно использовать курсор:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TABLE ttest(t_id INT NOT NULL, payload text);
INSERT INTO ttest VALUES (1, 'a'), (1, 'b'), (2, 'c');

BEGIN;
DECLARE cur_ttest CURSOR FOR SELECT * FROM ttest WHERE t_id = 1 /* ORDER BY something */ LIMIT 1 FOR UPDATE;
MOVE FIRST IN cur_ttest;
UPDATE ttest SET payload = 'updated' WHERE CURRENT OF cur_ttest;
CLOSE cur_ttest;
COMMIT;


Но, по-хорошему, первичные ключи должны быть на всех таблицах, тогда таких "проблем" не будет.
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642250
eg909ss0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Perederiy,

оба
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642400
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukPerederiyВ таблице есть несколько записей с id=333.
Необходимо обновить только одну из них.
Как это сделать ?

Ну например select ctid, * from SOMETABLE where id=333;
и далее обновляем через

update SOMETABLE SET ... WHERE id=333 and ctid=(какой нить из полученных на предыдущем шаге);

это если записи до байта совпадают (тоесть полные копии)
иначе добавляем условие на какое то из полей еще которое у них разное вместо условия на ctid.

--
Maxim Boguk
dataegret.ru

при партицированной табличке не забыть про тейблоид. иначе получится "как всегда"
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642471
Alex URS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk
Какой то бред вы написали... в таком виде оно вам вообще всю таблицу обновит.
Откуда у вас идея что так можно делать?


мда, ошибся. вот так будет работать:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
UPDATE table
SET ....
FROM (
SELECT xmin FROM table
where id = 333
ORDER BY id DESC LIMIT 1) as foo
WHERE table.xmin = foo.xmin




Код: plsql
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.
CREATE TABLE public.___t (
  id INTEGER,
  value VARCHAR
)

psql=# SELECT * FROM ___t;
 id  | value 
-----+-------
 332 | q
 334 | w
 333 | e
 333 | r
 333 | t
(5 rows)

psql=# UPDATE ___t
psql-# SET "value" = 'x'
psql-# FROM (
psql(# SELECT xmin FROM ___t
psql(# where id = 333
psql(# ORDER BY id DESC LIMIT 1) as foo
psql-# WHERE ___t.xmin = foo.xmin;
UPDATE 1
psql=# 
psql=# SELECT * FROM ___t;
 id  | value 
-----+-------
 332 | q
 334 | w
 333 | r
 333 | t
 333 | x
(5 rows)

...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642486
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex URS,

Да елки же зеленые...
И так тоже работать не будет... xmin легко может быть у всех строк в таблице одинаковым :) (а уж несколько записей с одинаковым xmin тем более нормально).
Это очень странная идея что xmin - как то вам уникальную строку задаст (и вы даже не проверяете что у нее id=333 до кучи).

--
Maxim Boguk
dataegret.ru
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642498
Alex URS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim BogukAlex URS,
Да елки же зеленые...


ну тогда так:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
ALTER TABLE public.___t  SET WITH OIDS;

UPDATE ___t
SET "value" = 'x'
FROM (
SELECT oid FROM ___t
where id = 333
ORDER BY id DESC LIMIT 1) as foo
WHERE ___t.oid = foo.oid


oid уникален в пределах таблицы
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642505
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex URSMaxim BogukAlex URS,
Да елки же зеленые...


ну тогда так:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
ALTER TABLE public.___t  SET WITH OIDS;

UPDATE ___t
SET "value" = 'x'
FROM (
SELECT oid FROM ___t
where id = 333
ORDER BY id DESC LIMIT 1) as foo
WHERE ___t.oid = foo.oid


oid уникален в пределах таблицы

Еще интереснее...
У 99.99% пользовательских таблиц в базе НЕТ колонки OID и никогда не будет.
Он только у системных таблиц есть.

PS: давайте вы всетаки изучите тему перед тем как советовать :).
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642507
Alex URS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot Maxim Boguk]Alex URSпропущено...


Еще интереснее...
У 99.99% пользовательских таблиц в базе НЕТ колонки OID и никогда не будет.
Он только у системных таблиц есть.

PS: давайте вы всетаки изучите тему перед тем как советовать :).

а это Вам ни о чём не говорит?
Код: plsql
1.
ALTER TABLE public.___t  SET WITH OIDS;


предлагаю Вам изучить, что это значит
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642513
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Alex URS]Maxim Bogukпропущено...


а это Вам ни о чём не говорит?
Код: plsql
1.
ALTER TABLE public.___t  SET WITH OIDS;


предлагаю Вам изучить, что это значит
очередной .
извините.
наше вам здрасьте.
не подскажете, с какого пж дефолтный with oids сменился на визаут ? и каковы причины отказа разработчиков от чемодана без ручки ?


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

неприятности начинаются когда вспоминают о партицировании -- там ключом записи (при доступе из головы наследования) будет оид-физич-партиции + цтид-внутри-оной. о чем при написании универсалий иногда забывают.
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642525
Alex URS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq]пропущено...

очередной .
дефолтный with oids .

он не WITH по дефолту. по умолчанию значение этого параметра — off (столбцы OID не добавляются); в PostgreSQL версии 8.0 и ранее он был включён (on).
https://postgrespro.ru/docs/postgrespro/10/runtime-config-compatible#GUC-DEFAULT-WITH-OIDS

В остальном Вы всё верно говорите, как и Maxim Boguk
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642703
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Alex URS]Maxim Bogukпропущено...


а это Вам ни о чём не говорит?
Код: plsql
1.
ALTER TABLE public.___t  SET WITH OIDS;


предлагаю Вам изучить, что это значит

Ага... полная перазапись условной 20Gb таблицы с полной блокировокой на это время...
И неслабый overhead по записи в будущем в нее.
С тем же успехом можно add id serial not null добавить, эффект тот же а для базы сииильно дешевле будет.

OID на пользовательской таблице - идея плохая.
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39642711
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwqочередной .
извините.
наше вам здрасьте.
не подскажете, с какого пж дефолтный with oids сменился на визаут ? и каковы причины отказа разработчиков от чемодана без ручки ?


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

Причины отказа:
1)4 байта в любую строку небесплатные сильно
2)выдача OID дорогая операция так как он shared по всей базе
3)а нафиг он вообще нужен в пользовательских таблицах?

И главное:
OID еще и нифига не уникален в таблице что вы легко обнаружите сделав таблицу с WITH OIDS в которой больше 2 с копейками миллиардов строк :)) (более того легко можно на долгосрочной работе получить небольшую таблицу с WITH OIDS и дублями). Поэтому даже WITH OIDS ничего вам на счет уникальности не гарантирует .
(На системных таблицах стоит защита от этого специальная... и уникальные индексы).
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39643490
Flashpoke
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
4.
5.
CREATE SEQUENCE test;

UPDATE mytable
SET id = 12345
WHERE id = 333 AND nextval('test') = 2;
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39643493
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flashpoke
Код: sql
1.
2.
3.
4.
5.
CREATE SEQUENCE test;

UPDATE mytable
SET id = 12345
WHERE id = 333 AND nextval('test') = 2;



А вот это действительно новый и интересный вариант да :).
Хотя я бы все таки nextval('test') = 1 сделал бы (на случай если такая строка одна).
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39644135
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flashpoke
Код: sql
1.
CREATE SEQUENCE test;

И drop в одной транзакции с create, чтобы обеспечить монопольный доступ к нужному значению.
...
Рейтинг: 0 / 0
Обновить ТОЛЬКО ОДНУ запись
    #39644161
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.Flashpoke
Код: sql
1.
CREATE SEQUENCE test;

И drop в одной транзакции с create, чтобы обеспечить монопольный доступ к нужному значению.

монополья уже есть :
Код: sql
1.
2.
3.
create temporary SEQUENCE test ;-- on commit drop; todo?

select  nextval('test') ;


https://www.postgresql.org/docs/current/static/sql-createsequence.html
остается рестартить на каждом стейтменте.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Обновить ТОЛЬКО ОДНУ запись
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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