PL/SQL constraint: Always one record in a table - sql

Im trying to add a constraint to a table so that there can only be one record in the table.
This is the code I already have:
ALTER TABLE CONFIG
ADD CONSTRAINT always_one
CHECK (count(*)= 1);
And this is the error I'm getting
ALTER TABLE CONFIG
ADD CONSTRAINT always_one CHECK (count(*)= 1)
Error report -
SQL Error: ORA-00934: group function is not allowed here
00934. 00000 - "group function is not allowed here"
*Cause:
*Action:
How does this work?

You can use already proposed solution with adding unique constraint on column
alter table config add constraint always_one check (pk_col=1);
this however allows inserting more than one row in case pk_col is null in second inserted row. So you need to handle this by adding a NOT NULL constraint as well
ALTER TABLE config
ADD CONSTRAINT notnulc CHECK (pk_col IS NOT NULL) ;
To prevent deleting this row, you should probably create before delete trigger as follows
create or replace trigger trg_ONLYONE before delete ON CONFIG
DECLARE
C NUMBER;
BEGIN
SELECT COUNT(*) INTO C FROM CONFIG;
if (C=1) THEN
RAISE_APPLICATION_ERROR (-20011, 'TOO FEW ROWS');
END IF;
END;
Futher options are: instead of check constraints mentioned above is CREATE BEFORE INSERT trigger, or instead of NOT NULL and UNIQUE CONSTRAINT make pk_col PRIMARY KEY

Just create a unique index on a column in the table, and add a constraint that the value of this column must be a certain value.
eg.
CREATE UNIQUE INDEX one_val ON config(pk_col);
ALTER TABLE CONFIG
ADD CONSTRAINT always_one
CHECK (pk_col = 1);
If all of your other columns could be any value, you may need to just add this additional column, and give it a default value.

Related

SQL constraint to exclude certain values?

Is there an sql constraint that enables you to disallow certain values in a column?
e.g.
ALTER TABLE foo
ADD COLUMN code TEXT NOT NULL UNIQUE DISALLOW '<GENERATE>'
;
s.t. <GENERATE> could be used safely in the application to indicate that the value should be generated before persisting without risking its accidentally being pushed to DB?
You need a check constraint:
ALTER TABLE foo
ADD COLUMN code TEXT NOT NULL UNIQUE;
alter table foo
add constraint disallow_generate
check (code <> '<GENERATE>');
If you want to disallowed multiple values, use a NOT IN condition:
alter table foo
add constraint disallow_generate
check (code not in ('<GENERATE>', '<GENERATED>', 'foo');
You could use Check Constraints.
eg:
ALTER TABLE foo
ADD COLUMN code TEXT NOT NULL UNIQUE CHECK (code <> '<GENERATE>');

How to add constraint to table in sql?

I create a table
create table CARS{
CAR_ID NUMBER(10), CONSTRAINT X_CAR_ID NOT NULL
}
and now I want to change the name of the constraint, so I drop the constraint:
ALTER TABLE CARS DROP CONSTRAINT X_CAR_ID;
This works correclty but, when I tried to add new constraint I have a problem,
my query:
ALTER TABLE CARS ADD CONSTRAINT XX_CAR_ID (CAR_ID) NOT NULL;
I thought that query, will be working correctly, but I get only error report:
Error report -
SQL Error: ORA-00904:
How to add correctly this constraint ?
While I couldn't test it I believe the statement below is what you want:
ALTER TABLE CARS MODIFY CAR_ID CONSTRAINT XX_CAR_ID NOT NULL;
Oracle uses the modify keyword in this context.
To rename it without dropping first you would use:
alter table cars rename constraint x_car_id to xx_car_id;
See the reference for more info.

Check constraint last_name capitalized

How can I make a check constraint that checks if last_name has the last 2 letters capitalized?
alter table clienti modify (nume_client constraint che_d check(nume_client=upper(substr(nume_client, -2, 1))));
I did like this, but I am getting the following error:
00000 - "cannot validate (%s.%s) - check constraint violated"
Your constraint is comparing the whole name to the upper-cased second-to-last character. It's only looking at one character, because you're supplying the third argument substring_length as 1. You need to check the last two characters; so you need to compare only those with the same two characters in upper-case:
substr(nume_client, -2) = upper(substr(nume_client, -2))
The error you are getting is because you have existing data which does not satisfy the constraint you are trying to add. That may be because your constraint isn't doing what you intended, as it will always return false in your original version.
If you get the same error with the modified check then you either need to remove or correct that data before you add the constraint, or use the novalidate clause:
check (substr(nume_client, -2) = upper(substr(nume_client, -2))) novalidate
Any existing constraint-violating rows will remain untouched, but you won't be able to add new rows that violate the constraint, or update existing rows to still-invalid values.
You can use your alter table modify (column...) syntax, or the simpler syntax Gordon Linoff showed; they do the same thing ultimately.
You might already have records there in table, that do not pass the check constraint. If it's OK to have the check only for future transactions you can use NOVALIDATE clause to constraint. E.g.
CREATE TABLE names (last_name VARCHAR2(100));
--Table created
INSERT INTO names VALUES ('Rambo');
--1 row inserted
INSERT INTO names VALUES ('GatES');
--1 row inserted
alter table names add constraint chk_che_d
check (SUBSTR(last_name,-2,1) = upper(substr(last_name, -2, 1))) NOVALIDATE;
--Table altered
INSERT INTO names VALUES ('Travolta');
--ORA-02290: check constraint (RO.CHK_CHE_D) violated
INSERT INTO names VALUES ('SkywalkER');
--1 row inserted
This is the syntax for adding a check constraint:
alter table clienti add constraint chk_che_d
check (nume_client = upper(substr(nume_client, -2, 1)));
I'm pretty sure the logic doesn't do anything useful (I'm pretty sure this will always return false). But the right syntax will get you on the right path.

add CHECK constraint to already populated table

I created a table called test with column called code:
create table test(
code char(3) not null);
I then populated the table with the following data:
insert into test values ('A12');
insert into test values ('B23');
insert into test values ('C45');
I then altered the column to make it char(4):
alter table test
alter column code char(4) not null;
I then added a 'X' to all existing data so that it becomes 4 characters long:
update test
set code='X'+code
where LEN(code)=3;
So far so good but then when I tried to add a check constraint:
alter table test
add constraint codeCheck check (code like 'A-Z''A-Z''0-9''0-9');
I got this error:
The ALTER TABLE statement conflicted with the CHECK constraint "codeCheck".
I understand that the error implies that the existing data violates the check constraint that I am trying to add into the table, but why?
and how do I do it such that the existing data and check constraint do not violate each other?
Your pattern syntax is wrong. It should be
alter table test
add constraint codeCheck check (code like '[A-Z][A-Z][0-9][0-9]');
Because your data doesn't match the like constraint.
Try
alter table test
add constraint codeCheck check (code like '[A-Z][A-Z][0-9][0-9]' );
I donĀ“t know how it works with SQL Server but your like clause looks odd.
Try using
'[A-Z]{2}\d{2}'

SQL: Create new column with default, unique value

I have added a new column, called Ordinal, to a table called Activity. The problem is that I gave it a UNIQUE constraint, set it to allow NULL (though this I won't want in the end.. I just needed to set it to that to get a little farther with the script), and did not give it a default value. I'm now running a RedGate SQL Compare script that was generated by comparing this table to a version of the Activity table that does not have the column. But I'm getting the following error:
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'iwt.Activity' and the index name 'IX_Activity'. The duplicate key value is (1).
So based on my research, it's trying to create a unique key constraint on the Ordinal column, but NULL is not unique. So my next step was to give it a unique value of 1 just to let the script pass. But 1 isn't going to be unique either. So, finally, my question:
Preferably in SQL Server Management Studio, how do I set a column as having a unique default value? Isn't that what I would need to create this constraint?
Thanks.
try this:
NULL will be the first constraint when you create the column.
UNIQUE will be as add constraint, you should add the second constraint.
they can run on this order with no problem (tested):
--first constraint
alter table Table_Name
add Column_Name int null
--second constraint
alter table Table_Name
add constraint Constraint_Name unique (Column_Name)
In my example :
PaymentGatewayHash is column
Cart is a table
--first query
alter table Cart
add PaymentGatewayHash NVARCHAR(20) null
--second query
CREATE UNIQUE INDEX PaymentGatewayHashUnique
ON Cart (PaymentGatewayHash)
WHERE PaymentGatewayHash IS NOT NULL
I just tested that :D