Creating a summary table violates a restriction - db2

I'm trying to union two MQTs containing in a MQT.
CREATE SUMMARY TABLE MYUNIONEDTABLE
AS (
SELECT * FROM MQT1
UNION ALL
SELECT * FROM MQT2
)
DATA INITIALLY DEFERRED REFRESH DEFERRED
ORGANIZE BY ROW;
Which leads to the following error:
The statement failed because the fullselect specified for the materialized query table "MYUNIONEDTABLE" violates a restriction. Reason code = "2".. SQLCODE=-20058, SQLSTATE=428EC, DRIVER=4.18.60
The SELECT statement itself works fine.

Did you check the Info Center article on this error?
SQL20058N
The statement failed because the fullselect specified for the
materialized query table table-name violates a restriction. Reason
code = reason-code.
Explanation
Restrictions apply to the contents of a fullselect used in the
definition of a materialized query table. Some restrictions are based
on the materialized query table options, such as REFRESH DEFERRED or
REFRESH IMMEDIATE. Other restrictions are based on whether or not the
table is replicated. The fullselect in the statement that returned
this condition violates at least one of these restrictions.
If this message is returned during the creation of a staging table,
the error applies to the query used in the definition of the
materialized query table with which the staging table is associated.
Reason code 2, as your error message shows, means:
The fullselect referenced an unsupported object type.
Take a look at the article for MQT restrictions to see what statement you are using that is unsupported.

Related

DB2 : SQL Error [42997]: Function not supported (Reason code = "21").. SQLCODE=-270, SQLSTATE=42997

I have to write a sql script to modify a lot of types of columns in my db2 database.
Everything goes well excpet for one specific table (script used is the same as others tables) and db2 returns always an error I don't understand.
Here is my script :
ALTER TABLE "TEST"."CLIENT"
ALTER COLUMN C_CODE
SET DATA TYPE CHAR(16 OCTETS);
and the error :
SQL Error [42997]: Function not supported (Reason code = "21")..
SQLCODE=-270, SQLSTATE=42997, DRIVER=4.26.14
I try to modify some others columns on the same table, but I always receive the same error.
Do you, by any chance, have an idea?
Thanks in advance
The error SQL0270N (sqlcode = -270) has many possible causes, and the specific cause is indicated by the "reason code".
In this case the "reason code 21" means:
A column cannot be dropped or have its length, data type, security,
nullability, or hidden attribute altered on a table that is a base
table for a materialized query table.
The documentation for this sqlcode on Db2-LUW is at:
https://www.ibm.com/docs/en/db2/11.5?topic=messages-sql0250-sql0499#sql0270n
Search for SQL0270N on that page, and notice the suggested user response:
To drop or alter a column in a table that is a base table for a materialized query table, perform the following steps:
1. Drop the dependent materialized query table.
2. Drop the column of the base table, or alter the length, data type, nullability, or hidden attribute of this column.
3. Re-create the materialized query table.

DB2 iseries materialized view refresh

I have created the following materialized query table:
CREATE TABLE SCHEMA.TABLE AS
(SELECT * FROM SCHEMA.TABLEEXAMPLE)
DATA INITIALLY DEFERRED
REFRESH DEFERRED
MAINTAINED BY USER
DISABLE QUERY OPTIMIZATION;
When I execute a REFRESH TABLE SCHEMA.TABLE it get locked for others users to read from it.
Reading this doc from IBM https://www.ibm.com/support/knowledgecenter/en/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000977.html
I tried to execute this statement:
REFRESH TABLE SCHEMA.TABLE ALLOW READ ACCESS
But I get the following error: SQL State: 42601 Unexpected keyword ALLOW
What I'm missing on statement? Is there other way to allow read access to materialized query table while it is beign updated?
MQTs on Db2 for IBM i lag behind the functionality available in Db2 for LUW.
I've never bother with them, instead an encoded vector index (EVI) with computed columns meets every need I've every considered. (Note that Db2 LUW doesn't have EVIs)
Per Mao's comment, you might try deleting an recreating the MQT with the following:
CREATE TABLE SCHEMA.TABLE AS
(SELECT * FROM SCHEMA.TABLEEXAMPLE)
DATA INITIALLY DEFERRED
REFRESH DEFERRED
MAINTAINED BY USER
DISABLE QUERY OPTIMIZATION
with NC;
But I think a refresh would still require exclusive access to the MQT.
The only options I can think of for "refreshing" an MQT while it is being used
programmatically , using either triggers on the base tables or perhaps a process that uses SQL to update a few rows at a time.
removing the DISABLE QUERY OPTIMIZATION and not accessing the MQT directly. Instead depend on the optimizer to access it when appropriate. Now you can create a version of it every few hours and the Db should start using the newer version for new queries. Once the older one is no longer being used, you delete it (or REFRESH it)

Appending array during Postgresql upsert & getting ambiguous column error

When trying to do a query like below:
INSERT INTO employee_channels (employee_id, channels)
VALUES ('46356699-bed1-4ec4-9ac1-76f124b32184', '{a159d680-2f2e-4ba7-9498-484271ad0834}')
ON CONFLICT (employee_id)
DO UPDATE SET channels = array_append(channels, 'a159d680-2f2e-4ba7-9498-484271ad0834')
WHERE employee_id = '46356699-bed1-4ec4-9ac1-76f124b32184'
AND NOT lower(channels::text)::text[] #> ARRAY['a159d680-2f2e-4ba7-9498-484271ad0834'];
I get the following error
[42702] ERROR: column reference "channels" is ambiguous Position: 245
The specific reference to channels it's referring to is the 'channels' inside array_append.
channels is a CITEXT[] data type
You may need to specify the EXCLUDED table in your set statement.
SET channels = array_append(EXCLUDED.channels, 'a159d680-2f2e-4ba7-9498-484271ad0834')
When using the ON CONFLICT DO UPDATE clause the values that aren't inserted because of the conflict are stored in the EXCLUDED table. Its an ephemeral table you don't have to actually make, the way NEW and OLD are in triggers.
From the PostgreSQL Manual:
conflict_action specifies an alternative ON CONFLICT action. It can be either DO NOTHING, or a DO UPDATE clause specifying the exact
details of the UPDATE action to be performed in case of a conflict.
The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the
existing row using the table's name (or an alias), and to rows
proposed for insertion using the special excluded table. SELECT
privilege is required on any column in the target table where
corresponding excluded columns are read.
Note that the effects of all per-row BEFORE INSERT triggers are reflected in excluded values, since those effects may have contributed
to the row being excluded from insertion.

Postgres pg_dump now stored procedure fails because of boolean

I have a stored procedure that has started to fail for no reason. Well there must be one but I can't find it!
This is the process I have followed a number of times before with no problem.
The source server works fine!
I am doing a pg_dump of the database on source server and imported it onto another server - This is fine I can see all the data and do updates.
Then I run a stored procedure on the imported database that does the following on the database which has 2 identical schema's -
For each table in schema1
Truncate table in schema2
INSERT INTO schema2."table" SELECT * FROM schema1."table" WHERE "Status" in ('A','N');
Next
However this gives me an error now when it did not before -
The error is
*** Error ***
ERROR: column "HBA" is of type boolean but expression is of type integer
SQL state: 42804
Hint: You will need to rewrite or cast the expression.
Why am I getting this - The only difference between the last time I followed this procedure and this time is that the table in question now has an extra column added to it so the "HBA" boolean column is not the last field. But then why would it work in original database!
I have tried removing all data, dropping and rebuilding table these all fail.
However if I drop column and adding it back in if works - Is there something about Boolean fields that mean they need to be the last field!
Any help greatly apprieciated.
Using Postgres 9.1
The problem here - tables in different schemas were having different column order.
If you do not explicitly specify column list and order in INSERT INTO table(...) or use SELECT * - you are relying on the column order of the table (and now you see why it is a bad thing).
You were trying to do something like
INSERT INTO schema2.table1(id, bool_column, int_column) -- based on the order of columns in schema2.table1
select id, int_column, bool_column -- based on the order of columns in schema1.table1
from schema1.table1;
And such query caused cast error because column type missmatch.

tracing the cause of "could not open relation with OID" error

Quite recently my PostgreSQL 8.2.4 logs such errors:
ERROR: could not open relation with OID nnnnnnnnn
CONTEXT: SELECT a,b,c FROM table_C
The error is always caused by the same scenario: an update to table A causes trigger to fire, which inserts data to table B, which fires another trigger, which (among many other things) does select on table C. That select on table C is then reported as CONTEXT of the problem above. The sequence of queries that cause the error message to appear is executed every day, and everyday it complains about the same OID missing.
Quite naturally the OID mentioned in error message doesn't exists when querying pg_class. Executing problematic SQL (that is, select on table C) doesn't cause any problems. I've tried to figure out the OIDs and connections between all the tables involved, to figure out where that reference to non-existent OID is, but i have failed. I started with table A and got its OID (pg_class.reltype) and verified, that it has trigger attached. The problems start when i query pg_trigger using pg_trigger.tgrelid = pg_class.reltype as a condition. The query yelds 0 rows, but when i query tables just by relname/tgname i get different OIDs, just like the trigger is on a different table. I did a quick test and it appears, that creating a simple table with a trigger on it produces the same result.
So my questions are:
How do i navigate pg_trigger (and other pg tables like pg_attribute, pg_shdepend) tables when i can locate table in pg_class?
If somehow I manage to find a reference to problematic OID, am I safe to simple remove the reference by doing direct updates/deletes on pg_class tables?
Note that 'reltype' is the OID of the table's rowtype- the OID of the table itself is pg_class.oid (which is a system column, so doesn't show up in \d or select * output, you need to select it explicitly).
Hopefully that will solve some mysteries of how the catalogue tables relate to each other! The same pattern is repeated with quite a few other tables using oid as their primary key.
It looks like quite a serious problem, possibly indicating some sort of catalogue corruption? You can modify pg_class et al directly, but obviously there is some risk involved in doing that. I can't think of much generic advice to give here- what to do will vary greatly depending on what you find.
If this appears while executing statements inside SQL function, then change the language from SQL to plpgsql. The cause can be a cached plan. plpgsql function invalidates plan between runs, while sql function seems to skip this step.
Verify your tables at backend, PostgreSQL assigns an unique OID for each table created.
Try to insert data at data base side then do it through application.
I was facing the same issue and struggled for long.