2013-06-10 1 views
2

У Ive возникла следующая проблема. Я хочу изменить некоторые значения инструкции INSERT, например. есть запрос:Изменить значения перед вставкой в ​​таблицу/PostgreSQL

INSERT INTO table(a,b) values(x,y); 

Но таблица имеет также еще один столбец с. Я хочу проверить (до INSERT) значение b из запроса выше и в зависимости от его значения, тогда установите c = z, но только для этой конкретной строки, которую я только что вставил.

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

ответ

2

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

create table foo (
    a integer, 
    b integer, 
    c integer); 

--== Create table. Yes, it is no PK, but for example it is not necesarry 

create or replace function p_foo_insert(in aa integer, in ab integer) returns integer as 
$$ 
declare 
    result integer; 
begin 
    insert into foo (a, b, c) values (aa, ab, aa + ab) returning c into result; 
    return result; 
end; $$ language plpgsql; 

--== It is function for row insertion. Inside this function you can do any data manipulation. 

select p_foo_insert(1, 2); 

--== Test statement. Result must be a + b = 1 + 2 = 3 

Итак, забудьте о insert into, использование хранимых процедур: о)

+0

Отлично! Спасибо @Abelisto, вот что мне нужно. Кстати, я написал несколько триггеров раньше, и я надеюсь, что они также должны работать, но последний ошибочный запрос разбил, какой триггер действительно сделал. Я потерял много часов на этом, а :) – kozooh

+0

@kozooh Надеюсь, мой ответ был полезен. Кстати, я вижу, что вы отмечаете свой вопрос как «postgresql-8.4». Я не помню точно, но в некоторых 9.x бранч PG становится быстрее, по крайней мере, x2 раза при вставке данных. Итак, попробуйте обновить: o) – Abelisto

1

Вы можете сделать это в самом заявлении INSERT, без необходимости запуска.

t Учитывая таблицу:

CREATE TEMP TABLE t (a int, b int, c int) 

По умолчанию для c является NULL.
Рассмотрим эту демку:

WITH i(x,y,z) AS (
    VALUES 
    (1, 2, 111) 
    ,(1, 7, 666) 
    ) 
INSERT INTO t(a,b,c) 
SELECT x, y, CASE WHEN y = 2 THEN z ELSE NULL END 
FROM i 
RETURNING * 

WITH (требует Postgres 9.1+) и пункт RETURNING только для тестирования удобства.
Важной частью является SELECT с заявлением CASE.

Этот тест должен работать на стр 8.4:

INSERT INTO t(a,b,c) 
SELECT x, y, CASE WHEN y = 2 THEN z ELSE NULL END 
FROM (
    VALUES 
    (1, 2, 111) 
    ,(1, 7, 666) 
    ) i (x,y,z) 
RETURNING * 
+0

поблагодарить Вас за напомнить мне о 'п with'. Это то, что является жемчужиной PG, и я всегда забываю программиста Oracle: o) Но я не уверен, что это применимо к исходному вопросу. – Abelisto

+0

@Abelisto: Решение соответствует заданному вопросу. Функция plpgsql, вероятно, слишком сложна для этого простого случая. Если вы нуждаетесь в * функции, завершите оператор 'CASE' в функции SQL. –

+0

«Функция plpgsql, вероятно, слишком сложна для этого простого случая». - Да, я согласен. Но это наша практика: ограничить доступ к объектам БД для обычных пользователей/программистов, кроме хранимых процедур. Это удобно, безопасно, и это помогает сохранить приложение-логику на стороне сервера. – Abelisto

 Смежные вопросы

  • Нет связанных вопросов^_^