我已经创建了一个表并为某些列添加了默认值。
例如
Create table Table1( COL1 NUMBER(38,0),
COL2 STRING,
MODIFIED_DT STRING DEFAULT CURRENT_DATE(),
IS_USER_MODIFIED BOOLEAN DEFAULT 'FALSE' )
当前行为:
在数据加载期间,我看到在运行插入时,将使用默认值插入我的列“ MODIFIED_DT”。
但是,如果有任何后续更新,则默认值不会得到更新。
预期行为:
我的要求是,任何INSERT / UPDATE操作都应自动注意列值。 例如。在SQL Server中,如果添加默认值,则每当对记录进行DML操作时,列值将始终使用默认值插入/更新。 有办法使它起作用吗?还是默认值仅适用于插入?
是否可以将逻辑添加到DEFAULT值。 例如。在上表的示例中,对于IS_USER_MODIFIED列,我可以这样做:
当CURRENT_USER()='Admin_Login'然后'FALSE'否则'TRUE'结尾的情况
如果没有,雪花中是否还有另一个选项可以实现这种功能?
答案 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())
);