Vertica: проверка данных дубликата / первичного ключа

Я пытаюсь создать процедуру проверки во время загрузки, которая проверяет, не дублируются ли данные. Vertica не поддерживает Это изначально:

Vertica проверяет наличие нарушений ограничений при выполнении запросов, а не при загрузке данных. Для обнаружения нарушений ограничений в рамках загрузите процесс, используйте инструкцию COPY (page 667) с фиксацией NO выбор. Загружая данные без фиксации, вы можете запустить post-load проверка данных с помощью Функция ANALYZE_CONSTRAINTS. Если функция находит нарушения ограничений, можно откатить нагрузку потому что вы не совершали этого.

проблема в том, что я не могу понять, как это сделать программно. Я подозреваю, что мне нужна хранимая процедура, но я не знаком с синтаксисом/ограничениями хранимых процедур для vertica. Вы можете помочь? Вот что у меня есть:

-- Create a new table. "id" is auto-incremented and "name" must be unique
CREATE TABLE IF NOT EXISTS my_table (
id IDENTITY
, name varchar(50) UNIQUE NOT NULL
, type varchar(20)
, description varchar(200)
);

--Insert a record
begin; 
copy my_table from stdin
abort on error
NO COMMIT; -- this begins the load
name1|type1|description1 --this is the load
. -- this closes the load
commit;

-- insert the duplicate record
begin; 
copy my_table from stdin
abort on error
NO COMMIT; -- this begins the load
name1|type1|description1 --this is the load
. -- this closes the load
commit; -- Surprisingly, the load executes successfully! What's going on?!?!

-- Check constraints. We see that there is a failed constraints:
select analyze_constraints('my_table');

мое мышление состоит в том, чтобы сделать некоторую условную логику. Psudo-код ниже. Вы можете поможешь мне подготовить его для Вертики?

Begin
load data
if (select count(*) from (select analyze_constraints('my_table')) sub) == 0:
commit
else rollback

3 ответов


-- Start by Setting Vertica up to rollback and return an error code 
-- if an error is encountered.

\set ON_ERROR_STOP on

-- Load Data here (code omitted since you already have this)


-- Raise an Error condition by selecting 1/0 if any rows were rejected
-- during the load
SELECT
         GET_NUM_REJECTED_ROWS() AS NumRejectedRows
        ,GET_NUM_ACCEPTED_ROWS() AS NumAcceptedRows
;

SELECT 1 / (1-SIGN(GET_NUM_REJECTED_ROWS()));


-- Raise an Error condition if there are duplicates in my_table
SELECT 1 / ( 1 - SIGN( COUNT(*) ) )
FROM ( SELECT  name1,type1,description1
         FROM MY_TABLE
       GROUP BY 1,2,3
       HAVING COUNT(*) > 1 ) AS T1 ;

-- Raise an Error if primary key constraint is violated.
SELECT 1 / ( 1 - SIGN( COUNT(*) ) )
FROM (SELECT  ANALYZE_CONSTRAINTS ('my_table')) AS T1;

COMMIT;    

Vertica не имеет хранимых процедур. Вам нужно будет сделать это программно каким-то образом за пределами Vertica.

логика psuedo у вас хорошая; просто реализуйте ее в чем-то (JAVA, C++, ect). Вам не нужно будет выполнять "откат". При загрузке данных (с NO COMMIT), Это не будет совершено, пока вы выполняете COMMIT заявление.


Как насчет использования слияния ansi?

-загрузите данные с помощью быстрого загрузчика в временную таблицу - Слияние из таблицы temp в базовую таблицу