DB2 cannot create MQT table - db2

I am trying to create DB2 MQT table in my DB2 v10.5, but I got the following error message:
An unexpected token "CREATE TABLE T_MQT AS (
SELECT ID, COL1, C" was found following "BEGIN-OF-STATEMENT". Expected tokens may include: "".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.16.53 SQL Code: -104, SQL State: 42601
Here is my create table statement:
CREATE TABLE T (
ID VARCHAR(128) NOT NULL,
COL1 VARCHAR(128),
COL2 VARCHAR(128),
COL3 VARCHAR(128),
COL4 VARCHAR(128),
COL5 VARCHAR(128),
PRIMARY KEY (ID)
);
CREATE TABLE T_MQT AS (
SELECT ID, COL1, COL2, COL3 FROM T
)
DATA INITIALLY DEFERRED
REFRESH IMMEDIATE
SET INTEGRITY FOR T_MQT IMMEDIATE CHECKED NOT INCREMENTAL;

You're missing a semicolon between the CREATE TABLE T_MQT ... statement and the SET INTEGRITY statement.

I found the reason is the base table is "ORGANIZE BY COLUMN". So I changed the sql to
CREATE TABLE T (
ID INTEGER NOT NULL,
COL1 VARCHAR(128),
COL2 VARCHAR(128),
COL3 VARCHAR(128),
COL4 VARCHAR(128),
COL5 VARCHAR(128),
PRIMARY KEY (ID)
) ORGANIZE BY ROW;
CREATE TABLE T_MQT ( ID, COL1, COL2, COL3 )
AS ( select ID, COL1, COL2, COL3 from T )
DATA INITIALLY DEFERRED REFRESH IMMEDIATE MAINTAINED BY SYSTEM;
SET INTEGRITY FOR T_MQT IMMEDIATE CHECKED FULL ACCESS;

Related

postgresql: how to add timestamp and primary id to this random table SQL

I have the following random table data sql
create table foo as select random() as col1,
left(md5(i::text), 10) as col2,
md5(random()::text) as col3,
left(md5(random()::text), 4) as col4,
from generate_series(1,10) s(i)
It creates 10 rows of data.
But now I want to add col5 (timestamp) <-- just like creation time (its auto inserted) when the row is added
and also a col0 - primary unique key
You can use
select
row_number() OVER () AS row,
now() as col5,
...

Upsert/merge into postgres table with distinct null in unique columns

I have a requirement to upsert into a table.
test_table(col1 varchar, col2 varchar, col3 varchar, col4 varchar)
The condition is that col1,col2 and col3 should be unique and it should allow distinct null.
I have tried using a unique index , I think we need to have a constraint as we need to upsert into the table. and using the below index is slow while upserting into the table
create unique index idx on test_table(coalesce(col1,'null'),(col2,'null'),(col3,'null'),)

Does column order matter when defining unique constraints

How is this
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
col1 VARCHAR(50) NOT NULL,
col2 VARCHAR(50) NOT NULL,
col3 DOUBLE PRECISION NULL,
UNIQUE(col1, col2)
);
Different from this?
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
col1 VARCHAR(50) NOT NULL,
col2 VARCHAR(50) NOT NULL,
col3 DOUBLE PRECISION NULL,
UNIQUE(col2, col1) -- reversed column ordering
);
From what I understand both commands will generate an index on the two columns to enforce the unique constraint but with different ordering.
So I would not need to generate a separate index to speed up queries like this in either case.
SELECT id, col3 FROM foo WHERE col1 = 'stack' AND col2 = 'overflow'
However if future queries will also involve querying by column "col2" alone like below the latter form is preferred because the index will still be usable right?
SELECT id, col3 FROM foo WHERE col2 = 'overflow'
The order matters if you expect to ever use the index as a partial index. For example, suppose you had a unique index on (col1, col2), and you wanted to optimize the following query:
SELECT col1, col2 FROM foo WHERE col1 = 'stack';
The index on (col1, col2) could still be used here, because col1, which appears in the WHERE clause, is the leftmost portion of the index. Had you defined the unique constraint on (col2, col1), the index could not be used for this query.

PostgreSQL: Drop column and recreate dependent views

I have below test table and dependent views created.
create table test_col_drp (col1 varchar(100), col2 varchar(100), col3 varchar(100));
create view test_col_drp_vw1 as select col1 col1_vw1, col2 col2_vw1, col3 col3_vw1 from test_col_drp;
create view test_col_drp_vw2 as select col1_vw1 col1_vw2, col2_vw1 col2_vw2, col3_vw1 col3_vw2 from test_col_drp_vw1;
I'm trying to drop a column from the table but getting below error:
alter table test_col_drp drop column col3;
ERROR: cannot drop table test_col_drp column col3 because other objects depend on it
DETAIL: view test_col_drp_vw1 depends on table test_col_drp column col3 view test_col_drp_vw2 depends on view test_col_drp_vw1
HINT: Use DROP ... CASCADE to drop the dependent objects too.
********** Error **********
What would be the best way to drop the column and recreate all the dependent views?
Working on:
PostgreSQL 9.6.6 on x86_64-pc-mingw64, compiled by gcc.exe (Rev5, Built by MSYS2 project) 4.9.2, 64-bit
Windows 10
First, you have to drop the views. Then, execute the alter table and finally create the views again. See:
-- This is what you have in your database
create table test_col_drp (col1 varchar(100), col2 varchar(100), col3 varchar(100));
create view test_col_drp_vw1 as select col1 col1_vw1, col2 col2_vw1, col3 col3_vw1 from test_col_drp;
create view test_col_drp_vw2 as select col1_vw1 col1_vw2, col2_vw1 col2_vw2, col3_vw1 col3_vw2 from test_col_drp_vw1;
-- drop views and alter table
drop view test_col_drp_vw2;
drop view test_col_drp_vw1;
alter table test_col_drp drop column col3;
-- creating the views again without col3
create view test_col_drp_vw1 as select col1 col1_vw1, col2 col2_vw1 from test_col_drp;
create view test_col_drp_vw2 as select col1_vw1 col1_vw2, col2_vw1 col2_vw2 from test_col_drp_vw1;
An alternative is to use the drop cascade. In this case, you do not need to drop each view individually but you still need to recreate them:
alter table test_col_drp drop column col3 cascade;
-- creating the views again without col3
create view test_col_drp_vw1 as select col1 col1_vw1, col2 col2_vw1 from test_col_drp;
create view test_col_drp_vw2 as select col1_vw1 col1_vw2, col2_vw1 col2_vw2 from test_col_drp_vw1;
Another option is to create a SQL command that generates your alter table using cascade and the create view:
with query_result as (
SELECT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
, pg_attribute.attname as column_name
, row_number() over() as id
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
AND pg_depend.refobjsubid = pg_attribute.attnum
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE 1=1
-- AND source_ns.nspname = 'public'
AND source_table.relname like 'test_col_drp%'
AND pg_attribute.attnum > 0
AND pg_attribute.attname = 'col3'
)
select concat('alter table ', source_table, ' drop column ' , column_name, ' cascade;' ) as sql_command from query_result where id = 1
union all
select concat('create or replace view ', dependent_view, ' as select * from ', source_table, ';') as sql_command from query_result
Then, the output will be:
alter table test_col_drp drop column col3 cascade;
create or replace view test_col_drp_vw1 as select * from test_col_drp;
create or replace view test_col_drp_vw2 as select * from test_col_drp_vw1;

NOT NULL constraint on a column when another column has a particular value

create table test (
col1 varchar(20),
col2 varchar(20)
)
When col1 has value '1', col2 cannot be null.
When col1 has any other value, col2 can be null.
Is there a way to write a check constraints based on values of particular columns?
You can write a table-level constraint, sure.
CREATE TABLE test (
col1 VARCHAR(20),
col2 VARCHAR(20),
CHECK (col1 != '1' OR col2 IS NOT NULL)
);
Either col1 isn't '1' (and col2 can be anything), or col1 is '1' (and col2 can't be null).
See the third example in the manual.