CREATE TABLE T1 ... LIKE ... creating table with cluster key if source table defined with cluster key in SNowflake - cluster-analysis

It is mentioned in documents that the snowflake does not propagate cluster key from the source table if the table is created with 'CREATE TABLE .... LIKE.....';
From Documentation :
• An existing Clustering key is not propagated when a table is created using CREATE TABLE … LIKE.
CREATE
OR replace TABLE
CUST_1GB_CL ***cluster BY (C_CUSTKEY)*** (
C_CUSTKEY NUMBER(38, 0) NOT NULL
,C_NAME VARCHAR(25) NOT NULL
,C_ADDRESS VARCHAR(40) NOT NULL
,C_NATIONKEY NUMBER(38, 0) NOT NULL
,C_PHONE VARCHAR(15) NOT NULL
,C_ACCTBAL NUMBER(12, 2) NOT NULL
,C_MKTSEGMENT VARCHAR(10)
,C_COMMENT VARCHAR(117)
);
create table CUST_1GB_CL3 like CUST_1GB_CL;
GET_DDL('TABLE', 'CUST_1GB_CL3')
CREATE
OR replace TABLE
CUST_1GB_CL3 ***cluster BY (C_CUSTKEY)*** (
C_CUSTKEY NUMBER(38, 0) NOT NULL
,C_NAME VARCHAR(25) NOT NULL
,C_ADDRESS VARCHAR(40) NOT NULL
,C_NATIONKEY NUMBER(38, 0) NOT NULL
,C_PHONE VARCHAR(15) NOT NULL
,C_ACCTBAL NUMBER(12, 2) NOT NULL
,C_MKTSEGMENT VARCHAR(10)
,C_COMMENT VARCHAR(117)
);

This is strange. I think following up with Snowflake on this is best course of action.
If you want you can drop the clustering key in your new table as follows:
ALTER TABLE IF EXISTS CUST_1GB_CL3 DROP CLUSTERING KEY;

Related

Default constraint not being enforced

Given the following table definition:
CREATE TABLE ControlledSubstances.NationalDrugCode
(
NationalDrugCodeID INT NOT NULL
,NationalDrugCode VARCHAR(20) NOT NULL
,Product VARCHAR(100)
,Ingredient VARCHAR(500)
,ClassID VARCHAR(50)
,Class VARCHAR(50)
,DrugEnforcementAgencyClassID VARCHAR(50)
,DrugEnforcementAgencyClass VARCHAR(50)
,GenericDrug VARCHAR(50)
,Form VARCHAR(50)
,Drug VARCHAR(50)
,StrengthPerUnit NUMERIC(6,2)
,UnitOfMeasure VARCHAR(50)
,ConversionFactor NUMERIC(4,2)
,LongOrShortActing VARCHAR(50)
,IsPreventionForStates BIT NOT NULL
)
;
ALTER TABLE ControlledSubstances.NationalDrugCode
ADD CONSTRAINT PK_ControlledSubstances_NationalDrugCode PRIMARY KEY (NationalDrugCodeID)
,CONSTRAINT DF_ControlledSubstances_NationalDrugCode_IsPreventionForStates DEFAULT 0 FOR IsPreventionForStates
;
CREATE UNIQUE INDEX UQ_ControlledSubstances_NationalDrugCode_NationalDrugCode ON ControlledSubstances.NationalDrugCode (NationalDrugCode);
Why would I be receiving an error on insert for the column I defined as NOT NULL and created a default constraint of 0? I know I can handle the logic in the insert statement to not pass in NULL values, but I use this logic in multiple tables and have never gotten an error before. The error I receive is:
Cannot insert the value NULL into column 'IsPreventionForStates', table 'Staging.ControlledSubstances.NationalDrugCode'; column does not allow nulls. INSERT fails.
This will happen if you explicitly provide NULL as its value. The default constraint only kicks in when you don't supply a value at all, or when you use the DEFAULT keyword:
For example, if NationalDrugCodeID and IsPreventionForStates were your only two columns in the table (for illustration), this will fail:
INSERT INTO NationalDrugCode(NationalDrugCodeID, IsPreventionForStates) VALUES (5, NULL);
But either of these would work:
INSERT INTO NationalDrugCode(NationalDrugCodeID) VALUES (5);
INSERT INTO NationalDrugCode(NationalDrugCodeID, IsPreventionForStates) VALUES (5, DEFAULT);
In the edge case where you need ALL columns to have default values inserted, you can use:
INSERT INTO NationalDrugCode DEFAULT VALUES;

How to insert to Postgresql geometry column

I have a WKT data which looks like so:
GEOMETRYCOLLECTION(
POINT(-1763555.1165955865 310640.0829509564),
POINT(-1421117.229877997 -300856.1433304538)
)
The default projection is 'EPSG:3857'. In postgresql I created a parent table whith generic geometry column and several child tables with columns of specific geometry type. The schema looks like so:
# parent table with generic geometry column "geom"
CREATE TABLE "public"."layer_261_" (
"id" int4 DEFAULT nextval('layer_261__id_seq'::regclass) NOT NULL,
"feature_id" int4 DEFAULT 0 NOT NULL,
"feature_name" varchar(200),
"feature_type" varchar(50),
"geom" "public"."geometry",
"object_id" int4 DEFAULT 0 NOT NULL,
"row_id" int4 DEFAULT 0 NOT NULL
)
WITH (OIDS=FALSE);
ALTER TABLE "public"."layer_261_" ADD CHECK (st_srid(geom) = 3857);
ALTER TABLE "public"."layer_261_" ADD CHECK (st_ndims(geom) = 2);
ALTER TABLE "public"."layer_261_" ADD PRIMARY KEY ("id");
# child table which is supposed to contain only POINT data type
CREATE TABLE "public"."layer_261_points" (
"id" int4 DEFAULT nextval('layer_261__id_seq'::regclass) NOT NULL,
"feature_id" int4 DEFAULT 0 NOT NULL,
"feature_name" varchar(200),
"feature_type" varchar(50),
"geom" "public"."geometry",
"object_id" int4 DEFAULT 0 NOT NULL,
"row_id" int4 DEFAULT 0 NOT NULL
)
INHERITS ("public"."layer_261_")
WITH (OIDS=FALSE);
ALTER TABLE "public"."layer_261_points" ADD CHECK (st_ndims(geom) = 2);
ALTER TABLE "public"."layer_261_points" ADD CHECK (geometrytype(geom) = 'POINT'::text);
ALTER TABLE "public"."layer_261_points" ADD CHECK (st_srid(geom) = 3857);
So, how can I insert my data (two points to the database)? For example, I'm not sure whether I should convert points' coordinates to lat-lon. And besides, I'm not sure whether I should insert GEOMETRYCOLLECTION or all points one by one.
EDIT
I've just tried to execute a query with a real data point:
INSERT INTO layer_261_ (geom) VALUES (ST_Point(105177.3509204, -85609.471679397))
But as a result I got this error message:
new row for relation "layer_261_" violates check constraint
"enforce_srid_geom"
Does anybody know how to fix it?
EDIT
This query leads to the very same error message:
INSERT INTO layer_261_ (geom) VALUES (ST_SetSRID(ST_Point(105177.3509204, -85609.471679397),
4326))
You can only insert the WKT into the parent table because the point table won't accept a GEOMETRYCOLLECTION:
INSERT INTO "public"."layer_261_" ("geom", <other columns>)
VALUES (ST_GeomFromText(<your WKT>, 3857), <other values>);
Once you have the data in the parent table you can easily convert from the GEOMETRYCOLLECTION to separate POINTs using ST_Dump() and insert those in the point table:
INSERT INTO "public"."layer_261_points" ("geom", <other columns>)
SELECT p.geom, <other columns>
FROM "public"."layer_261_" m, ST_Dump("geom") p
WHERE ...;
You can of course also forget about the first step and do ST_Dump(ST_GeomFromText(<your WKT>, 3857)) in the second step but that is less intuitive and more prone to errors.
Note that ST_Dump() is a table function so it should be used in a FROM clause. It can then use columns from tables specified before the function.
The error you were getting from using ST_Point() is because you the geometry has a NULL SRID. You should set that explicitly with ST_SetSRID() (one of my great annoyances with PostGIS...).

Postgres before insert trigger using sequence from another table

Using Postgres, what I would like to achieve is to be able to have many different instrument types, with corresponding [TYPE].instrument tables, which all have a unique ID in the table, but also reference a unique ID in the instrument.master table. I have the following:
create schema instrument
CREATE TABLE instrument.type (
id smallserial NOT NULL,
name text not null,
code text not null,
CONSTRAINT pk_instrument_type PRIMARY KEY (id)
);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_code UNIQUE(code);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_name UNIQUE(name);
insert into instrument.type (name, code) values ('futures', 'f');
CREATE TABLE instrument.master (
id serial NOT NULL,
type smallint not null references instrument.type (id),
timestamp timestamp with time zone not null,
CONSTRAINT pk_instrument_master PRIMARY KEY (id)
);
CREATE TABLE futures.definition (
id smallserial NOT NULL,
code text not null,
CONSTRAINT pk_futures_definition PRIMARY KEY (id)
);
ALTER TABLE futures.definition ADD CONSTRAINT unq_futures_definition_code UNIQUE(code);
insert into futures.definition (code) values ('ED');
CREATE TABLE futures.instrument (
id smallserial NOT NULL,
master serial not null references instrument.master (id),
definition smallint not null references futures.definition (id),
month smallint not null,
year smallint not null,
CONSTRAINT pk_futures_instrument PRIMARY KEY (id),
check (month >= 1),
check (month <= 12),
check (year >= 1900)
);
ALTER TABLE futures.instrument ADD CONSTRAINT unq_futures_instrument UNIQUE(definition, month, year);
CREATE OR REPLACE FUNCTION trigger_master_futures()
RETURNS trigger AS
$BODY$
BEGIN
insert into instrument.master (type, timestamp)
select id, current_timestamp from instrument.type where code = 'f';
NEW.master := currval('instrument.master_id_seq');
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
create trigger trg_futures_instrument before insert on futures.instrument
for each row
execute procedure trigger_master_futures();
I then test with:
insert into futures.instrument (definition, month, year)
select id, 3, 2015 from futures.definition where code = 'ED';
Everything works almost as I would like it to. The only issue is that somehow, instrument.master.id ends up being one more than futures.instrument.master. I am not sure what I need to do to achieve the behavior I want, which is that whenever an entry is inserted into futures.instrument, an entry should be inserted into instrument.master, and the id entry of the latter should be inserted into the master entry of the former. I actually think it should have failed since the foreign key relationship is violated somehow.
As it turns out, everything was correct. The issue was that in futures.instrument, the type of the master column is serial, and it should have been int.

pgAdmin - When trying to make a foreign key "referencing" gives no options

I have three tables: ModelingAgency.clients, ModelingAgency.models, ModelingAgency.Bookings. All three tables have a primary key column called id.
The table bookings has two columns that reference clients and models. In pgAdmin when I try to create a foreign key in bookings to either clients or models I get the following screens:
What am I overlooking here? I am new to PostgreSQL (This is my first test project with PostgreSQL -- I've always used MySQL and occasionally SQL Server) so it's probably something obvious (I just don't see it).
EDIT: Here is the DDL, as requested:
-- Table: "ModelingAgency.bookings"
-- DROP TABLE "ModelingAgency.bookings";
CREATE TABLE "ModelingAgency.bookings"
(
id integer NOT NULL DEFAULT nextval('"ModelingAgency.Bookings_id_seq"'::regclass),
"clientId" integer NOT NULL,
"modelId" integer NOT NULL,
"time" timestamp with time zone NOT NULL DEFAULT now(),
"location" character varying(100) NOT NULL DEFAULT 'No Location Selected'::character varying,
CONSTRAINT "bookingId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.bookings" OWNER TO "MyBatisTutorial";
-- Table: "ModelingAgency.clients"
-- DROP TABLE "ModelingAgency.clients";
CREATE TABLE "ModelingAgency.clients"
(
id integer NOT NULL DEFAULT nextval('"ModelAgency.clients_id_seq"'::regclass),
"name" character varying(45) NOT NULL,
CONSTRAINT "clientId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.clients" OWNER TO "MyBatisTutorial";
-- Table: "ModelingAgency.models"
-- DROP TABLE "ModelingAgency.models";
CREATE TABLE "ModelingAgency.models"
(
id serial NOT NULL,
"name" character varying(45) NOT NULL,
CONSTRAINT "modelId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.models" OWNER TO "MyBatisTutorial";
Looking into your posted DDL code I see that your table's names are written in wrong way (that causes your issue with pgAdmin):
"ModelingAgency.bookings"
It should be in format "schema"."tableName":
"ModelingAgency"."bookings"
After that Object browser looks like this (probably you need to create schema first using easily pgAdmin or with CREATE SCHEMA SQL statement):
Here is working DDL code (I omitted some things like OIDS and OWNER TO, but that doesn't matter to your case, BTW OIDS are false on default):
DROP TABLE IF EXISTS "ModelingAgency"."bookings";
CREATE TABLE "ModelingAgency"."bookings"
(
id serial,
"clientId" integer NOT NULL,
"modelId" integer NOT NULL,
"time" timestamp with time zone NOT NULL DEFAULT now(),
"location" character varying(100) NOT NULL
DEFAULT 'No Location Selected'::character varying,
CONSTRAINT "bookingId" PRIMARY KEY (id)
);
DROP TABLE IF EXISTS "ModelingAgency"."clients";
CREATE TABLE "ModelingAgency"."clients"
(
id serial,
"name" character varying(45) NOT NULL,
CONSTRAINT "clientId" PRIMARY KEY (id)
);
DROP TABLE IF EXISTS "ModelingAgency"."models";
CREATE TABLE "ModelingAgency"."models"
(
id serial NOT NULL,
"name" character varying(45) NOT NULL,
CONSTRAINT "modelId" PRIMARY KEY (id)
)

Junction tables in T-SQL

In my database application, when I try to attach a page to a site, I get the following error:
System.InvalidOperationException: Can't perform Create, Update or Delete operations on 'Table(Junc_Page_Site)' because it has no primary key.
I intend a page to be able to be added to multiple sites - by using a junction table.
Below is the schema for the three tables in question (T-SQL). Any advice will be appreciated!
CREATE TABLE Site (
Id INTEGER NOT NULL IDENTITY ,
FkSiteId INTEGER ,
Name NVARCHAR(64) NOT NULL ,
Domain NVARCHAR(128) ,
Theme NVARCHAR(32) ,
ThemeVariation NVARCHAR(32) ,
PRIMARY KEY(Id) ,
FOREIGN KEY(FkSiteId)
REFERENCES Site(Id));
GO
CREATE TABLE Page (
Id INTEGER NOT NULL IDENTITY ,
Title NVARCHAR(64) NOT NULL ,
Description NVARCHAR(256) NOT NULL ,
Keywords NVARCHAR(1024) NOT NULL ,
ScriptName NVARCHAR(64) ,
PRIMARY KEY(Id));
GO
CREATE TABLE Junc_Page_Site (
FkPageId INTEGER NOT NULL ,
FkSiteId INTEGER NOT NULL ,
FOREIGN KEY(FkSiteId)
REFERENCES Site(Id),
FOREIGN KEY(FkPageId)
REFERENCES Page(Id));
GO
You're almost there. You just need to create what's called a "composite primary key", which is to say that you need to tell the database that the conbination of FkPageId and FkSiteId will be unique:
CREATE TABLE Junc_Page_Site (
FkPageId INTEGER NOT NULL ,
FkSiteId INTEGER NOT NULL ,
FOREIGN KEY(FkSiteId)
REFERENCES Site(Id),
FOREIGN KEY(FkPageId)
REFERENCES Page(Id),
PRIMARY KEY (FkPageId, FkSiteId));