List check constraints of Teradata table - constraints

I need to get list of all check constraints related to given table. For example, if there table
create table table_with_check
( S_BYTEINT BYTEINT NOT NULL,
CONSTRAINT CHECK_CONSTR CHECK(S_BYTEINT > 10)
)
I have only full table name and I need a query that returns me name of check constraint("CHECK_CONSTR") and its expression(S_BYTEINT > 10). The only thing I've found is system table DBC.ConstraintName but there only check constraint name but not expression.

There's no system table named DBC.ConstraintName in Teradata.
There's a view dbc.Table_LevelConstraintsV, based DBC.TableConstraints, which contains info about table level constraints like your CHECK_CONSTR and named constraints on column level. If you got an unnamed column constraint it's found in dbc.ColumnsV.ColumnConstraint.

Related

Adapt ON CONFLICT clause to new unique index?

I want to add an extra unique constraint to an existing table. This and other answers say it's not possible with sqlite, and suggest creating an unique index:
ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
This seems to work. However, I'm having trouble with UPSERTs:
INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';
This gives an error:
ON CONFLICT cause does not match any PRIMARY KEY or UNIQUE constraint
Is there any way I could adapt the ON CONFLICT clause of the statement above to work with the new "constraint"?
I tried using new_unique_index, to no avail. If it's impossible, is there any alternative to creating a new table with the new unique constraint and copying the values from the old table into the new one with NULL for the new constraint column? This would be burdensome. I imagine I could create a new table with all of the former's columns, except the old uniques, plus the new unique, and link them somehow, but it sounds messy and I have no idea how to proceed.
Minimum reproducible example:
CREATE TABLE example (foo TEXT, old_unique TEXT, UNIQUE(old_unique));
ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';
Is there any way I could adapt the ON CONFLICT clause of the statement above to work with the new "constraint"?
(old_unique, new_unique) is a not a possible constraint target as there is no index that combines both columns, each is an individual constraint (so you could use one or the other, as my understanding is that you are limited to a single UPSERT clause and a single conflict target).
If instead of :-
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
You used
CREATE UNIQUE INDEX new_unique_index ON example(old_unique,new_unique);
Then the following will work :-
INSERT INTO example (foo,old_unique,new_unique) VALUES('foo','old','new') ON CONFLICT (old_unique,new_unique) DO UPDATE SET foo = 'foo';
(well at least not be rejected due to no covering primary key or index for the given conflict target).
If it's impossible, is there any alternative to creating a new table with the new unique constraint and copying the values from the old table into the new one with NULL for the new constraint column? This would be burdensome.
It's not really burdensome e.g. you could use :-
CREATE TABLE IF NOT EXISTS temp_example (foo, old_unique,new_unique, UNIQUE(old_unique,new_unique));
INSERT INTO temp_example SELECT *,null FROM example;
ALTER TABLE example RENAME TO old_example;
ALTER TABLE temp_example RENAME TO example;
DROP TABLE If EXISTS old_example;
i.e. as you are adding a column and it will be the last column then there is no need to code column names.

In Teradata there get columns/fields used by join and where condition and respective table without parsing query

I am trying to automate some performance check on query in Teradata.
So as part of that I want to check if columns used in joining condition are primary index of respective table or not and similarly for columns used in where condition are partition column in respective table or not. Is there any direct Teradata query which can directly give this without parsing whole query.
Yes there are two dbc objects where you can query :
dbc.columnsv
dbc.indicesv.
Primary index information will be stored in the 2nd view just search with your tablename and database name.
Partitioned information is stored in columnsv , there is a column with a flag value 'Y' for partitioned columns.
Example :
SELECT DATABASENAME,TABLENAME,COLUMNNAME FROM DBC.COLUMNSV WHERE PARTITIONINGCOLUMN='Y' where tablename=<> and databasename=<>;
Select * from dbc.indicesv where tablename=<> and databasename=<>;

How to handle date type in SQLite?

I've created a table, where I have "Date of birth" column of date type. The problem is that I can insert anything and it's successfully done. I want that field to restrict opportunities like inserting strings and not related stuff.
insertions
wrongResults
I've searched for the solution, but I could only find codes for getting the current time in different formats. I also don't get how exactly modifiers work (https://www.sqlite.org/lang_datefunc.html).
Bar the rowid column or an alias of the rowid column, any type of value can be stored in an type of column. That is the type of column does not restrict/constrain the data that can be stored.
p.s. there is no DATE type rather due to SQLite's flexibility DATE actually has a type (type affinity) of NUMERIC (not that that matters that much). You might find Datatypes In SQLite Version 3 an interesting read or perhaps this How flexible/restricive are SQLite column types?.
the rowid and, therefore an alias thereof, column MUST be an integer. Although typically you allow SQLite to assign the value.
You should either check the data programatically or alternately use a CHECK constraint when defining the column in the CREATE TABLE SQL.
A CHECK constraint may be attached to a column definition or specified
as a table constraint. In practice it makes no difference. Each time a
new row is inserted into the table or an existing row is updated, the
expression associated with each CHECK constraint is evaluated and cast
to a NUMERIC value in the same way as a CAST expression. If the result
is zero (integer value 0 or real value 0.0), then a constraint
violation has occurred. If the CHECK expression evaluates to NULL, or
any other non-zero value, it is not a constraint violation. The
expression of a CHECK constraint may not contain a subquery.
SQL As Understood By SQLite - CREATE TABLE
Example
Consider the following code :-
DROP TABLE IF EXISTS mychecktable ;
CREATE TABLE IF NOT EXISTS mychecktable (mycolumn BLOB CHECK(substr(mycolumn,3,1) = '-'));
INSERT INTO mychecktable VALUES('14-03-1900');
INSERT INTO mychecktable VALUES('1900-03-14'); -- ouch 3rd char not -
The is will result in :-
DROP TABLE IF EXISTS mychecktable
> OK
> Time: 0.187s
CREATE TABLE IF NOT EXISTS mychecktable (mycolumn BLOB CHECK(substr(mycolumn,3,1) = '-'))
> OK
> Time: 0.084s
INSERT INTO mychecktable VALUES('14-03-1900')
> Affected rows: 1
> Time: 0.206s
INSERT INTO mychecktable VALUES('1900-03-14')
> CHECK constraint failed: mychecktable
> Time: 0s
i.e. the first insert is successful, the second insert fails.
Usually you would enforce the correct format in your application, but you can also add constraints to your table definition to prevent this, e.g.,
CREATE TABLE users(...,
DoB TEXT CHECK(DATE(DoB) NOT NULL AND DATE(DoB)=DoB)
)

Oracle APEX validate Input during Data Load with Transformation Rule

In APEX, when performing a Data Load (e.g. upload of a csv file into APEX application), is it possible to validate input data using a transformation rule?
For example, suppose to upload data about cars that have been sold this month.
The target table has the column car_manufacturer and num_car_sold.
The column car_manufacturer must accept only three values, say ('A1', 'A2', 'A3').
In a pseudo PLSQL, just to give an idea:
IF :car_manufacturer IN ('A1, A2, A3') then :car_manufacturer else <error>
How can I check this in the upload phase? Is it possible to use a transformation rule, in order that if it fails, it returns an error message? Other ways?
Thanks in advance.
You could put a constraint on the table definition as per the other answer, or if you only want the error message for when the Data Load is used, you can use a Table Lookup.
Go to Shared Components -> Data Load Definitions
Open the Data Load Definition that you want to edit
Create Table Lookup
Select the column (e.g. car_manufacturer)
Set the Table Lookup attributes to a table that contains the list of valid values (you'll need either a table or a view for this)
Leave Insert New Value set to No (If set to 'No' (the default) then a new record will not be created in the lookup table if the lookup column value(s) entered do not already exist. If set to 'Yes' then a record will be created in the lookup table using the upload column(s) and the Upload Key Column will be retrieved from the newly created record.)
Set Error Message to the message you want to return if a match is not found.
How about having a check constraint on the table for the column "car_manufacturer"?
ALTER TABLE TABLE_NAME
ADD CONSTRAINT CHECK_CAR_MANUFACTURER
CHECK ( CAR_MANUFACTURER in ('A1', 'A2', 'A3'));

SQLlite: strange "Abort due to constraint violation"

I'm trying to rename a column of a table. I have a lot of tables with the word "couleur" and I renamed "manually" to "bulle".
I've successfully renamed main_groupecouleurs to main_groupebulles. Now i'm working on main_groupe. I'm trying to rename groupe_couleurs_id to groupe_bulles_id
The SQL is quite self-explaining:
BEGIN TRANSACTION;
DROP INDEX main_groupe_fc5cee5b;
CREATE TABLE main_groupe7e12
(
id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
exemple TEXT,
groupe_bulles_id INTEGER DEFAULT NULL,
reference TEXT,
FOREIGN KEY (groupe_bulles_id) REFERENCES main_groupebulles(id)
DEFERRABLE INITIALLY DEFERRED
);
CREATE UNIQUE INDEX main_groupe_fc5cee5b ON main_groupe7e12 (groupe_bulles_id);
INSERT INTO main_groupe7e12(id, description, exemple, groupe_bulles_id, reference)
SELECT id, description, exemple, groupe_couleurs_id, reference
FROM main_groupe;
DROP TABLE main_groupe;
ALTER TABLE main_groupe7e12 RENAME TO main_groupe;
COMMIT;
When I run it, I get:
[SQLITE_CONSTRAINT] Abort due to constraint violation
(UNIQUE constraint failed: main_groupe7e12.groupe_bulles_id)
This means (I think I'm wrong here but I dont know what I'm missing) that it tries to insert some groupe_couleurs_id that are not in the referring table (= main_groupebulles). Thus I tried to see in the original table the problem:
SELECT * FROM main_groupe WHERE groupe_couleurs_id NOT IN (
SELECT id FROM main_groupebulles
);
I got no rows! What am I missing?
You have an UNIQUE index on your groupe_bulles_id column but based on the comments, there are a lot of valid duplicate values for that column coming from main_groupe.groupe_couleus_id and that causes the constraint violation.
Since having duplicate values is what you want, remove the UNIQUE from the CREATE UNIQUE INDEX ....

Resources