Ответы пользователя по тегу PostgreSQL
  • Как в Postgres запустить выражение, которое существует в виде строки?

    @romaro Автор вопроса
    Работает:
    DECLARE
        l_table_name	varchar(30) := lower(p_table_name);
    BEGIN
    	EXECUTE 'ALTER TYPE obj_name_tp ADD VALUE IF NOT EXISTS '||quote_literal(l_table_name);


    Во-первых, не было никакого смысла передавать значение переменной в качестве плейсхолдера, т.к. EXECUTE находится в области видимости блока BEGIN, в котором эта переменная задекларирована.

    Во-вторых, я пытался использовать функцию quote_ident(), которая оборачивает текст в двойные кавычки. Однако двойные кавычки (наряду с символами $$) используются для "прерывания" самого plpgsql-кода. Получалось, что я пытался вызвать ALTER TYPE без параметра, т.к. значение после EXISTS отсекалось.
    Ответ написан
    Комментировать
  • Почему не удается подключиться к Postgres(VirtualBox) из хостовой машины?

    @romaro Автор вопроса
    Проблема решилась одной строкой:
    firewall-cmd --add-port=5432/tcp --permanent

    Когда я пытался открыть порт через iptables, видимо, допустил ошибку в настройке корректного адреса. Наверное, сработало бы что-то вроде:
    iptables -A INPUT -p tcp -s 0.0.0.0/0 --dport 5432 -j ACCEPT


    В любом случае, предустановленный на Oracle Linux демон firewalld более дружелюбен для простых операций с настройкой сети, поэтому в моем случае не было особого смысла использовать iptables/nftables
    Ответ написан
  • Почему не удается сменить слушающий порт в контейнеризированном Postgres?

    @romaro Автор вопроса
    Решение было на поверхности. При установке Постгреса на Винду его драйвер занял порт 5433 (видимо я в момент установки уже использовал 5432 для подключения):
    62f424d551d68071028505.jpeg
    62f4250711b39620833364.jpeg

    Поэтому ошибка пароля была честной: я тупо ломился в базу на хостовой машине.
    Ответ написан
    Комментировать
  • Как можно удалить запись из Postgres через некоторое время?

    @romaro
    Если вы хотите обойтись средствами Пайтона, то вроде есть аналоги setInterval. Вы просто пишите функцию, которая срабатывает, например, раз в 10 минут и удаляет по выборке:
    cursor.execute('DELETE FROM user_info WHERE <Ваше условие>)
        connection.commit()


    Либо установите расширение для Постгрес вроде этого (у PG нет встроенного планировщика).

    Вам так же будет полезна эта статья.
    Ответ написан
    Комментировать
  • Sequence postgres?

    @romaro
    Вам, скорее всего, нужно в Постгресе поменять тип колонки id с int на serial (это аналог оракловых последовательностей). И не передавать при создании новой записи id, пусть его генерацией занимается субд.

    Или попробуйте обновить модель:
    /**
         * @var null
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(name="id", type="serial", nullable=false)
         */
    Ответ написан
  • Как создать команду для sql?

    @romaro
    Можно создать в базе функцию, которая принимает json:
    CREATE TABLE my_table (id BIGINT NOT NULL PRIMARY KEY, first_name VARCHAR(50) UNIQUE, last_name VARCHAR(50));
    
    CREATE FUNCTION add_obj (p_obj json)
    RETURNS int
    LANGUAGE plpgsql
    AS $$
    DECLARE
    	p_id int := p_obj ->> 'id';
    	p_name TEXT := p_obj ->> 'name';
    	p_last_name TEXT := p_obj ->> 'lastName';
    BEGIN 
    	INSERT INTO my_table (
    		id, first_name, last_name
    	) VALUES (
    		p_id, p_name, p_last_name
    	) RETURNING id;
    END;
    $$;


    Затем взять низкоуровневую библиотеку:
    npm i pg

    И с ее помощью дергать функцию:
    import pkg from 'pg';
    const { Pool } = pkg;
    
    export class PostgresDriver {
    	constructor(config) {
    		this.pool = new Pool(config);
    		this.pool.on('error', err => {
    			console.error('StoreDB Postgres error', err);
    		});
    	}
    
    	async getPoolClient() {
    		try {
    			return await this.pool.connect();
    		} catch (e) {
    			throw new Error('StoreDB -> poolConnect() ->', e.message);
    		}
    	}
    
    	async addObject(obj) {
    		const json = JSON.stringify(obj);
    		const sql = `CALL add_obj('${json}');`;
    		try {
    			const client = await this.getPoolClient();
    			const rs = await client.query(sql);
    			client.release();
    			return rs;
    		} catch (e) {
    			throw new Error(`PostgresDriver -> ${sql}`);
    		}
    	}
    }


    Но я бы рекомендовал переименовать id в ext_id и добавить к таблице безопасный первичный ключ с типом serial.
    Ответ написан
    Комментировать
  • Как задать колонке первоначальное значение?

    @romaro
    Можно создать в постгресе функцию или процедуру, используя concat():
    CREATE TABLE public.t (
    	id serial4 NOT NULL,
    	user_name varchar NULL,
    	phone varchar NULL,
    	CONSTRAINT t_pk PRIMARY KEY (id)
    );
    
    CREATE FUNCTION create_user (p_user_name varchar, p_phone varchar)
    RETURNS int
    LANGUAGE SQL
    AS $$
    	INSERT INTO t (
    		user_name, phone
    	) VALUES (
      		p_user_name, concat('+375', p_phone)
      	) RETURNING id;
      $$;


    И дергать ее таким образом:
    SELECT * FROM create_user('Иван', '7878785544');

    Функция будет возвращать Id только что созданного пользователя.
    Ответ написан
    Комментировать
  • Как создаются варианты одного товара в БД?

    @romaro
    Я в свое время разделил сущности товарной карточки (GOODS) и товарной позиции (PRODUCT). Товарная позиция является объектом складского учета (т.е. физически находится на складе), а товарная карточка всего лишь группирует эти позиции удобным способом и хранит фотографии, название, но не характеристики.

    Далее реализовал связь многие-ко-многим (одна товарная позиция может входить в состав нескольких товарных карточке), но это было черевато коллизиями двойных заказов, когда физически на складе одна единица товара, а пользователь добавил ее в корзину несколько раз через разные карточки. Конечно, транзакция не пройдет, но пользователь узнает об этом в последний момент, если не делать дополнительных уведомлений в интерфейсе.

    Поэтому при выгрузке из учетной системы я создавал третью сущность (ITEM), которая "виртуализировала" таблицу GOODS_PRODUCT. Таким образом, на сайте магазина у меня были GOODS и ITEM.goods, причем для ITEM.product был настроен уникальный индекс (для одного магазина нельзя было создать две карточки, на которые ссылается одна и та же товарная позиция).

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

    То есть важно понимать, что пользователь в конечном счете выбирает именно товарную позицию, а карточка - не более, чем страничка на сайте.
    Ответ написан
    Комментировать
  • В чем отличие Pool и Client конструкторов в NPM пакете pg?

    @romaro
    Дополню, что про пулы хорошо написано на этой странице из документации по node-postgres.
    Ответ написан