Как ограничить дублирование записи для вставки в таблицу в виде снежинки - PullRequest
3 голосов
/ 23 января 2020

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

create table tab11(id int primary key not null,grade varchar(10));

insert into tab11 values(1,'A');
insert into tab11 values(1,'B');

select * from tab11;

Вывод: вставлены дублирующиеся записи.

ID  GRADE
1   A
1   B

Ответы [ 4 ]

1 голос
/ 23 января 2020

Снежинка позволяет вам идентифицировать столбец как первичный ключ, но не обеспечивает уникальность для них. Из документации здесь :

Snowflake поддерживает определение и поддержание ограничений, но не применяет их, за исключением ограничений NOT NULL, которые всегда применяются.

Первичный ключ в Снежинке предназначен исключительно для информационных целей. Я не из Snowflake, но я представляю, что применение уникальности в первичных ключах не совсем соответствует тому, как Snowflake хранит данные за кулисами.

0 голосов
/ 24 января 2020

Вы можете попробовать использовать ПОСЛЕДОВАТЕЛЬНОСТЬ, чтобы соответствовать вашим требованиям

https://docs.snowflake.net/manuals/user-guide/querying-sequences.html#using -последовательности

0 голосов
/ 24 января 2020

Возможно, вы захотите использовать оператор слияния для обработки того, что происходит при поступлении строки с дублирующимся PK:

create table tab1(id int primary key not null, grade varchar(10));

insert into tab1 values(1, 'A');

-- Try merging values 1, and 'B': Nothing will be added
merge into tab1 using 
    (select * from (values (1, 'B')) x(id, grade)) tab2 
  on tab1.id = tab2.id
    when not matched then insert (id, grade)
                          values (tab2.id, tab2.grade);

select * from tab1;

-- Try merging values 2, and 'B': New row added
merge into tab1 using 
    (select * from (values (2, 'B')) x(id, grade)) tab2 
  on tab1.id = tab2.id
    when not matched then insert (id, grade)
                          values (tab2.id, tab2.grade);

select * from tab1;

-- If instead of ignoring dupes, we want to update:
merge into tab1 using 
    (select * from (values (1, 'F'), (2, 'F')) x(id, grade)) tab2 
  on tab1.id = tab2.id
    when matched then update set tab1.grade = tab2.grade
    when not matched then insert (id, grade)
                          values (tab2.id, tab2.grade);

select * from tab1;

Для более сложных слияний вы можете захотеть исследовать потоки Snowflake (изменить таблицы сбора данных). В дополнение к документации я создал сценарий SQL, в котором рассказывается, как использовать поток для синхронизации таблиц промежуточных и промежуточных файлов c:

https://snowflake.pavlik.us/index.php/2020/01/12/snowflake-streams-made-simple

0 голосов
/ 23 января 2020

Snowflake поддерживает следующие типы ограничений из стандарта ANSI SQL:

  • UNIQUE

  • PRIMARY KEY

  • ИНОСТРАННЫЙ КЛЮЧ

  • NOT NULL

Таблица может иметь несколько уникальных ключей и внешних ключей, но только один первичный ключ , Все внешние ключи должны ссылаться на соответствующий первичный или уникальный ключ, который соответствует типам столбцов каждого столбца во внешнем ключе. Первичный ключ для внешнего ключа может находиться в другой таблице или в той же таблице, что и внешний ключ.

Поскольку первичный ключ допускает дублирование, вы можете попробовать объединение.

DROP TABLE IF EXISTS tgt_tb; 

 create or replace temp table tgt_tb

 (id int, name string);



 DROP TABLE IF EXISTS src_tb; 

 create temp table src_tb

 (id int, name string);


 insert into src_tb

 select 1,'a'

 union all

 select 1,'a'

 union all

 select 2,'b'

 union all

 select 3,'c';


 insert into tgt_tb

 select 3,'c';

 DROP TABLE IF EXISTS src_stg_tb; 

 create temp table src_stg_tb

 as

select * from


(select *, ROW_NUMBER() OVER(PARTITION BY hash(*) order by hash(*) ) as rnm, hash(*) as hashkey

from src_tb 

) A

where A.rnm=1;


 merge into tgt_tb TGT 

 using src_stg_tb SRC 

on hash(tgt.id, tgt.name) = SRC.hashkey

when not matched then insert

Values (src.id,src.name) 
...