雪花表中DEFAULT选项的行为

时间:2020-10-12 13:15:05

标签: snowflake-schema

我已经创建了一个表并为某些列添加了默认值。
例如

Create table Table1( COL1 NUMBER(38,0),
                     COL2 STRING,                    
                     MODIFIED_DT STRING DEFAULT CURRENT_DATE(),
                     IS_USER_MODIFIED BOOLEAN DEFAULT 'FALSE' )

当前行为
在数据加载期间,我看到在运行插入时,将使用默认值插入我的列“ MODIFIED_DT”。 但是,如果有任何后续更新,则默认值不会得到更新。

预期行为

  1. 我的要求是,任何INSERT / UPDATE操作都应自动注意列值。 例如。在SQL Server中,如果添加默认值,则每当对记录进行DML操作时,列值将始终使用默认值插入/更新。 有办法使它起作用吗?还是默认值仅适用于插入?

  2. 是否可以将逻辑添加到DEFAULT值。 例如。在上表的示例中,对于IS_USER_MODIFIED列,我可以这样做:

    当CURRENT_USER()='Admin_Login'然后'FALSE'否则'TRUE'结尾的情况

    如果没有,雪花中是否还有另一个选项可以实现这种功能?

2 个答案:

答案 0 :(得分:0)

以下是大多数(所有?)数据库的通用信息,并非特定于Snowflake ...

仅当在INSERT语句中没有显式引用该列时,才插入表定义中列的默认值。因此,如果我有一个包含2列的表(column_a和column_b,并且column_b的默认值),并且执行了这种类型的INSERT:

version: "2.4"

# template:
x-base: &base-service-template
  env_file:
    - ./.env
  working_dir: /app/
  volumes:
    - ./src:/app/src:cached

services:

  service1:
    image: service1
    <<: *base-service-template

  service2:
    image: service2
    <<: *base-service-template

column_b将被设置为默认值。但是,使用以下INSERT语句:

FROM node:12-alpine as builder

ENV TZ=Europe/London
RUN npm i npm@latest -g
RUN mkdir /app && chown node:node /app
WORKDIR /app

RUN apk add --no-cache python3 make g++ tini \
    && apk add --update tzdata

USER node
COPY package*.json ./
RUN npm install --no-optional && npm cache clean --force
ENV PATH /app/node_modules/.bin:$PATH
COPY . .

FROM builder as dev
USER node
CMD ["nodemon", "src/services/service/service.js"]

FROM builder as prod
USER node
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "src/services/service/service.js"]

column_b的值为1,并且为null。因为我已经明确引用了column_b,所以即使该列定义具有默认值,我使用的值(即使它为NULL也会被写入记录)。

默认值仅适用于INSERT语句,不适用于UPDATE语句(因为现有记录在列中必须具有“值”,即使它是NULL值也是如此,因此当您对其进行更新时,默认值不适用)-因此我不认为您有关使用SQL Server更新的默认设置的说法是正确的;我只是尝试过,只是为了确定,但是没有。

雪花专用答案

鉴于该列默认设置仅适用于INSERT语句,因此它们不会解决您的问题。我能想到的唯一简单的解决方案是在INSERT / UPDATE语句中显式包括这些列。

您可以编写一个存储过程来执行INSERT / UPDATES,并自动填充这些列,但这对于批量更改而言效果不佳,使用起来可能并不简单,因为您需要传递表名,列列表和值列表。

很明显,如果您要使用外部工具插入/更新这些记录,则可以将此逻辑放入工具中,而不是尝试在Snowflake中实现。

答案 1 :(得分:0)

雪花具有“派生列”功能。这些列是虚拟/已计算的,在ETL过程中不使用。但是,任何DML活动都会自动影响列值。

很妙的是,我们甚至可以在列定义中编写CASE逻辑。这解决了我的问题。

CREATE OR REPLACE TABLE DB_NAME.DBO.TEST_TABLE
    (
            FILE_ID NUMBER(38,0), 
            MANUAL_OVERRIDE_FLG  INT           as (case when current_user() = 'some_admin_login' then 0 else 1 end), 
            RECORD_MODIFIED_DT   DATE          as (CURRENT_DATE()),
            RECORD_MODIFIED_BY   STRING        as (current_user()) 
    );