Why does this 'modify table' statement fail? - sql

I'm trying to add a 'not null' constraint to a column in Oracle 9.
ALTER TABLE user_roles modify group_id varchar2(36 char) set not null;
However, the operation fails with an odd error:
Error report:
SQL Error: ORA-12987: cannot combine drop column with other operations
12987. 00000 - "cannot combine drop column with other operations"
*Cause: An attempt was made to combine drop column with other
ALTER TABLE operations.
*Action: Ensure that drop column is the sole operation specified in
ALTER TABLE.
Any ideas why this is failing?

Remove set:
ALTER TABLE user_roles modify group_id varchar2(36 char) not null
And yes, Oracle's errors can be very misleading.

It turns out the syntax of the above statement is wrong. It should be:
ALTER TABLE user_roles modify group_id varchar2(36 char) not null;
Still, the presence of an erroneous 'set' leads to a very odd error!

I'm trying to add a 'not null'
constraint to a column in Oracle 9.
If you are really trying jsut to make the column NOT NULL (i.e. you don't want to change the datatype at the same time) you just need to
ALTER TABLE user_roles modify not null;

Related

Incorrect syntax near default in alter table

I want to alter the existing column Site_SiteId in SQL Server to make it as not null with default value 1 but getting a syntax error:
ALTER TABLE dbo.ImagingEvents
ALTER COLUMN Site_SiteId bit NOT NULL DEFAULT 1
default is a constraint so you need to add it to the table:
ALTER TABLE dbo.ImagingEvents ADD DEFAULT 1 FOR Site_SiteId
First you need to ALTER the column:
ALTER TABLE dbo.ImagingEvents ALTER COLUMN Site_SiteId bit NOT NULL;
Note that if you have any rows that already have the value NULL you will need to UPDATE them first, before performing the ALTER.
Then, personally, I would recommend creating a named constraint, like so:
ALTER TABLE dbo.ImagingEvents ADD CONSTRAINT DF_Site_SiteId DEFAULT 1 FOR Site_SiteId;
Having named constraints, rather than the automatically named ones, is far better for transferable code.

Error in changing column length in Postgres

I am trying to change the column size from 100 to 150 varchar data type using following query:
alter table data_warehouse.tbl_abc
alter column first_nm varchar(150) null;
Getting the following error:
SQL Error [42601]: ERROR: syntax error at or near "varchar"
Position: 77
The syntax is a bit different, so try this:
ALTER TABLE data_warehouse.tbl_abc
ALTER COLUMN first_nm type varchar(120);
The error in your syntax is that you missed a TYPE keyword:
ALTER TABLE data_warehouse.tbl_abc
ALTER COLUMN first_nm TYPE varchar(150);
and if you have a NOT NULL constraint you want to remove, add a new ALTER COLUMN inside the same ALTER TABLE statement:
ALTER TABLE data_warehouse.tbl_abc
ALTER COLUMN first_nm TYPE varchar(150),
ALTER COLUMN first_nm DROP NOT NULL;
for reference look here: https://www.postgresql.org/docs/current/sql-altertable.html
Edit: as in the comment, if you have a view which involves the same column, drop it and re-create it under transaction:
BEGIN TRANSACTION;
DROP VIEW [...];
ALTER TABLE [...];
CREATE VIEW [...];
COMMIT;
Be aware that to alter a table, you must acquire an exclusive lock on it, so during the whole process, all the queries over the same table and on the views of the table are locked, also if they don't read from the altered column (because the whole table is locked) - use with caution in production environment

Syntax error with if column on exist with primary key

I want to add a column which's also a primary key if it doesn't already exist on the table. If I do a simple
ALTER TABLE webinars_identities ADD COLUMN IF NOT EXISTS id uuid
It will work but if I do
ALTER TABLE webinars_identities ADD COLUMN IF NOT EXISTS id uuid PRIMARY KEY DEFAULT uuid_generate_v4();
It says it skips the alter table, but for some reason crashes right after:
NOTICE: column "id" of relation "webinars_identities" already exists, skipping
ERROR: multiple primary keys for table "webinars_identities" are not allowed
My original working query was
ALTER TABLE webinars_identities id uuid PRIMARY KEY DEFAULT uuid_generate_v4();
But this is not repeatable without error.
What am I doing wrong here ?
Handle it using duplicate_column exception and issue a notice, because someone rightly said that errors should never pass silently.
DO $body$
BEGIN
ALTER TABLE atable ADD COLUMN id int primary key; --DEFAULT uuid_generate_v4()
EXCEPTION
WHEN duplicate_column THEN
RAISE NOTICE 'ERROR: %,%',SQLSTATE,SQLERRM;
END $body$;
This will work the first time and does not fail on all following attempts, but gives you a message. All other errors if found in your statement will be raised as exceptions.
NOTICE: ERROR: 42701,column "id" of relation "atable" already exists
DO
Try this.
DO $$ BEGIN TABLE atable ADD COLUMN IF NOT EXISTS id int primary key ; exception when others then null ; END$$;
It's a bug in postgres https://www.postgresql.org/message-id/13277.1566920001%40sss.pgh.pa.us
Will be fixed in v13.0, hopefully.

Postgresql unable to change the data type of a column

I am new to Postgresql, and I am trying to change the data type of a column from Integer to Varchar(20), but I get strange error:
ERROR: operator does not exist: character varying <> integer :
No operator matches the given name and argument type(s).
You might need to add explicit type casts.********** Error **********
The script I wrote to create the table is:
CREATE TABLE LOGIN(
USERNAME INTEGER NOT NULL CHECK(USERNAME != NULL),
PASSWORD VARCHAR(10) NOT NULL CHECK(PASSWORD <>'' AND USERNAME != NULL)
);
This is the script I used to modify the column from Integer to Varchar:
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20);
I appreciate any help. Thanks.
Use USING expression. It allows you to define value conversion:
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20) USING ...expression...;
From PostgreSQL documentation:
The optional USING clause specifies how to compute the new column
value from the old; if omitted, the default conversion is the same as
an assignment cast from old data type to new. A USING clause must be
provided if there is no implicit or assignment cast from old to new
type.
The cause of the error is the useless additional check constraint (<> null) that you have:
operator does not exist: character varying <> integer :
refers to the condition USERNAME != NULL in both of your check constraints.
(the "not equals" operator in SQL is <> and != gets re-written into that)
So you first need to get rid of those check constraints. The default generated name for that check would be login_username_check, so the following will most probably work:
alter table login
drop constraint login_username_check;
The other check is most probably login_check:
alter table login
drop constraint login_check;
Once those check constraints are dropped you can alter the data type:
ALTER TABLE LOGIN
ALTER COLUMN USERNAME set data TYPE varchar(20);
Now you need to re-add the constraint for the password:
alter table login
add constraint check_password check (password <> '');
If for some reason the generated constraint names are different then the ones I assumes, you can find the names using:
select c.conname, c.consrc
from pg_constraint c
join pg_class t on c.conrelid = t.oid
join pg_namespace n on t.relnamespace = n.oid
where t.relname = 'login'
and n.nspname = 'public'; --<< change here for the correct schema name
As jarlh has already commented, defining a column as NOT NULL is enough. There is no need to add another "not null" check. Plus: the check is wrong anyway. You can't compare a value against null using = or <>. To test for a not null value you need to use IS NOT NULL. The correct way to write an explicit check constraint would be
username check (username is not null)
The problem is in USERNAME's CHECK constraint. You may get a way out of it using catalog pg_constraint somehow like that:
SELECT conname, consrc
FROM pg_constraint
WHERE conrelid =
(SELECT oid
FROM pg_class
WHERE relname LIKE 'login');
In a field 'consrc' you may notice that constraints actually look like "(username <> NULL::integer)", and it brings an error when you try to change column type from integer to varchar.
To remove constraints use
ALTER TABLE LOGIN DROP CONSTRAINT login_username_check;
ALTER TABLE LOGIN DROP CONSTRAINT login_check;
where 'login_username_check' and 'login_check' are connames you got from query above (be careful and doublecheck that names).
After that you should try to
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20);
This should work if your table has no data in it. If it doesn't, add a
ALTER TABLE dev.tests_LOGIN ALTER COLUMN USERNAME TYPE varchar(20) USING USERNAME::VARCHAR;
Than you probably want to restore PASSWORD<>'' check, so you'll have to do one more alter to bring it back. Good luck!
Some PostgreSQL documentation you may find handy:
pg_constraint doc
alter doc
PS: As mentioned above, you don't need to get a constraint (!=NULL) check when you already have NOT NULL in column description. Also, NULL checks are a bit different. Quick illustration:
SELECT (NULL = NULL);
SELECT (NULL != NULL);
SELECT (NULL IS NULL);
SELECT (NULL IS NOT NULL);

how to add check constraints for date columns

I am getting this error
ORA-02438: Column check constraint cannot reference other columns
when I am performing this query
alter table Issue
modify Issue_Date not null check (Issue_Date <= sys_date);
as well as I have to add this condition also (issue_date<return_date);
and when I tried this
alter table Issue
add constraint ck_Issue_Date not null check (Issue_Date <= sys_date);
ERROR ORA-00904: : invalid identifier
I suspect you are wanting to reference the Oracle SYSDATE function, not a column named sys_date.
Unfortunately, the conditions in a CHECK CONSTRAINT cannot reference the SYSDATE function.
To get the database enforce this type of restriction on the value of a column, that would require a TRIGGER.
For example, something like this:
CREATE OR REPLACE TRIGGER trg_issue_issue_date_biu
BEFORE INSERT OR UPDATE ON Issue
FOR EACH ROW
BEGIN
IF (NEW.Issue_Date <= SYSDATE) THEN
NULL;
ELSE
RAISE_APPLICATION_ERROR(-20000, 'Invalid: Issue_Date is NULL or >SYSDATE');
END IF;
END;
You tried to mix up inline column level constraint and table level constraint (for more than 1 column). Please simply split them on 2 statements:
alter table Issue
modify Issue_Date not null;
alter table Issue
add constraint ck_Issue_Date check (Issue_Date <= sys_date);
alter table Issue
add constraint ck_Issue_Date2 check (issue_date<return_date);