Exchange column order of table after it is created - sql

I have created a table with 4 columns. I need to change the structure of the table. I need to interchange the position of the 4th and 2nd columns permanently. Is this possible in Oracle?

Not possible. See this.
Oracle only allows columns to be added to the end of an existing
table.
So you must drop and recreate the tables.

You can run a script like this:
CREATE TABLE TMP_TBL as SELECT * FROM TBL_ORIG;
ALTER TABLE TBL_ORIG ADD COLUMN COL3;
DROP TABLE TBL_ORIG;
CREATE TABLE TBL_ORIG AS SELECT COL1, COL3, COL2 FROM TMP_TBL;
DROP TABLE TMP_TBL
You would need to consider indexes as well as storage concerns.

Why in the world is this necessary? Column order means nothing in SQL.

Swap of columns col1 and col2
It is assumed that col1 is int and col2 is varchar2(20)
-- drop all indexes and constraints concerning col1 and col2
alter table your_table add temp_col int; -- type of col1
update your_table set col1 = null, temp_col = col1;
alter table your_table modify col1 varchar2(20); -- type of col2
update your_table set col2 = null, col1 = col2;
alter table your_table modify col2 int; -- type of col1
update your_table set col2 = temp_col;
alter table your_table drop column temp_col;
alter table your_table rename column col1 to temp_col;
alter table your_table rename column col2 to col1;
alter table your_table rename column temp_col to col1;
-- recreate indexes and constraints

Simply rename table columns if they are the same datatype. If not then Alter - see Sean and Egor examples.
Rename:
http://docs.oracle.com/cd/E11882_01/server.112/e25494/tables006.htm#ADMIN11662
And on the interview they are looking for Sean's answer. Just FYI...

Related

How can i define a CHECK CONSTRAINT to enforce the rule of minimum 3 instances of a value?

I have a table that looks like this:
Table1(col1,col2,col3)
I want to define a CHECK CONSTRAINT that enforce a rule that there must be a minimum of 3 instances of a value in a column.
Something like this:
ALTER TABLE Athletes_Participations
ADD CONSTRAINT Check_participations CHECK (count(AID) >= 3)
The error message that get is:
An aggregate may not appear in a computed column expression or check constraint.
this is what i've tried:
CREATE FUNCTION CHECKINSTANCES()
RETURNS int
AS
BEGIN
DECLARE #retval int
SELECT #retval = COUNT(AID) FROM tbl1
RETURN #retval
END;
GO
ALTER TABLE tbl1
ADD CONSTRAINT CHK_INS CHECK (dbo.CHECKINSTANCES() >= 3 );
GO
As has been mentioned in the comments, this is messy. You can't do this with a CONSTRAINT alone, which means you either need to use a TRIGGER or a scalar function. I dislike using scalar functions in CONSTRAINTs, they have been known to tank performance, so I'm using a TRIGGER here.
Note that either implementation comes with caveats. Firstly, if you are inserting new rows you cannot insert them one by one. This will fail (as the first row will fail the pseudo CONSTRAINT). You won't be able to do task like UPDATE 1 row to have the value of new value, and INSERT 2 new rows either (with the same new value) as when the first statement completes the error will be thrown (due to there only being 1 or 2 rows). You'd have to use "proxy rows" to get around that. I demonstrate this below.
All in all, I suggest a design rethink.
CREATE TABLE dbo.YourTable (col1 int NOT NULL,
col2 varchar(10) NOT NULL,
col3 date NOT NULL);
GO
CREATE TRIGGER dbo.YourTable_Min3Col1 ON dbo.YourTable
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT 1
FROM dbo.YourTable YT
WHERE YT.Col1 IN (SELECT i.col1
FROM inserted i
UNION ALL
SELECT d.col1
FROM deleted d)
GROUP BY Col1
HAVING COUNT(Col1) < 3)
--Use an error code appropriate for you
THROW 79845, N'A check rule in the trigger ''YourTable_Min3Col1'' has failed. Less than 3 instances of a value of in the column ''Col1'' exist. The statement has been aborted.', 16;
END;
GO
--Succeeds
INSERT INTO dbo.YourTable (col1,
col2,
col3)
VALUES(1,'abc',GETDATE()),
(1,'def',GETDATE()),
(1,'xyz',GETDATE());
GO
--Fails
INSERT INTO dbo.YourTable (col1,
col2,
col3)
VALUES(2,'abc',GETDATE()),
(2,'def',GETDATE());
GO
--Succeeds
INSERT INTO dbo.YourTable (col1,
col2,
col3)
VALUES(3,'abc',GETDATE()),
(3,'def',GETDATE()),
(3,'xyz',GETDATE()),
(3,'opq',GETDATE());
GO
--Fails, despite that at the end of the batch there would be 3 rows with a value of 4
INSERT INTO dbo.YourTable (col1,
col2,
col3)
VALUES(4,'abc',GETDATE()),
(4,'def',GETDATE());
UPDATE dbo.YourTable
SET col1 = 4
WHERE col1 = 3
AND col2 = 'opq';
GO
--Use a "proxy" row to enforce it works
INSERT INTO dbo.YourTable (col1,
col2,
col3)
VALUES(4,'abc',GETDATE()),
(4,'def',GETDATE()),
(4,'def','19000101');
UPDATE dbo.YourTable
SET col1 = 4
WHERE col1 = 3
AND col2 = 'opq';
DELETE
FROM dbo.YourTable
WHERE Col1 = 4
AND Col3 = '19000101';
GO
--Fails, would reduce below 3
DELETE
FROM dbo.YourTable
WHERE col1 = 1
AND col2 = 'xyz';
GO
SELECT *
FROM dbo.YourTable;
GO
DROP TABLE dbo.YourTable;
db<>fiddle

Create automatically generated timestamp column in table?

How to create a automatically generated timestamp column in table in Microsoft SQL Server 2019? Timestamp column should be automatically generated when I insert or update table.
In IBM Db2 database the syntax is the following:
create table myschema.mytable (col1 int, col2 timestamp not null generated always for each row on update as row change timestamp
insert into myschema.mytable (col1) values (1)
update myschema.mytable set col1 = 2
After insert/update of column col1, column col2 is automatically generated as current timestamp.
In Microsoft SQL Server you can try this code:
CREATE TABLE myschema.mytable
(
col1 int,
col2 datetime not null default(current_timestamp)
)
INSERT INTO myschema.mytable(col1) VALUES (1)
UPDATE myschema.mytable SET col1 = 2
SELECT * FROM myschema.mytable
Update:
Let's create temporary table for test
DECLARE #mytable TABLE
(
col1 int,
col2 datetime not null default(current_timestamp)
)
INSERT INTO #mytable(col1) VALUES (1)
SELECT * FROM #mytable
UPDATE #mytable SET col1 = 2
SELECT * FROM #mytable

Exclude column in redshift spectrum sql queries

In my table having columns col1,col2.....coln
I want to
select all columns except col1
instead of writing select col2,col3.... coln from I can specify
select * from <table name> except col1
Select all column excluding one column
You can do something like this-
-- create a temporary copy of your table
SELECT * INTO temp_table FROM original_table;
-- drop the column you don't need
ALTER TABLE temp_table DROP COLUMN col1;
-- select all columns
SELECT * FROM temp_table;
-- drop the temporary table
DROP TABLE temp_table;

Query for Merge values from 3 column and merge as Primary Key in Oracle

In one table few columns are there and in 3 columns i want to merge values from these 3 columns and generate as Primary key after merging these 3 values.
Col1 having Datatype length 4, While col2 & col3 having datatype length 5 & 3 respectively. In col2 & col3 if any values are less than the maximum length then use LPAD with 0 and then after Merge into the Primary Key.
Ex- If col1 = 1234, col2 = 142, col3 = 32 then after merging It should be like "123400142032" as Primary Key.
You probably need something like this.
CREATE TABLE yourtable
(
col1 NUMBER,
col2 NUMBER,
col3 NUMBER
);
ALTER TABLE yourtable ADD (ID NUMBER GENERATED ALWAYS AS ( LPAD(col1,4,0)||LPAD(col2,5,0)||LPAD(col3,3,0) ) );
ALTER TABLE yourtable ADD CONSTRAINT t_test_pk PRIMARY KEY (ID) USING INDEX;
You may then insert only 3 columns and the column id gets automatically populated with a number such as 123400142032.
INSERT INTO yourtable (col1, col2, col3)
VALUES (1234, 142, 32);
Note : The create table script is just for understanding. You may not need it since you already have an existing table.
The virtual column syntax GENERATED .. AS works only in 11g and above. For lower versions, you may require a before insert trigger and a sequence.
with lp as
(select max(length(employee_id)) mp from employee),
llp as
(select max(length(first_name)) mf from employee)
select lp.*,lpad(employee_id,lp.mp,'0'),llp.*, lpad(first_name,llp.mf,'0'),
employee_id||lpad(employee_id,lp.mp,'0')||lpad(first_name,llp.mf,'0')from lp,llp,employee;
note: here employee_id and first_name are the columns, you can assume it as column1 and column2..

Extending tables in SQL

How to add a column to the table:
create table table1 (id integer primary key, field1 text)
? The column would be field2 text and the value for existing rows in this column should be value.
For MySQL:
ALTER TABLE table1 ADD field2 text;
UPDATE table1 SET field2='value';
That would be the SQL syntax:
ALTER TABLE table_name ADD column_name datatype
In your case, you'd be looking at:
alter table table1 add field2 text
update table1 set field2 = 'value'