Is there any way to move an column in an Oracle table from last to first position? Someone has dropped the ID column, and recreated it. So now it is at the end, which is a problem because some of our PHP Scripts are using the first column as an identifier (one Abstract Model with more than 100 other Models using this base object...)
See also:
In Oracle, is it possible to “insert” a column into a table?
Inserting new columns in the middle of a table?
The Oracle FAQ says:
Oracle only allows columns to be added to the end of an existing table.
You'd have to recreate your table.
RENAME tab1 TO tab1_old;
CREATE TABLE tab1 AS SELECT id, <the rest of your columns> FROM tab1_old;
the simplest way to modify the logical order of the columns of a table is to rename your table and create a view with the "right" column positions:
ALTER TABLE your_table RENAME TO your_table_t;
CREATE VIEW your_table AS SELECT <columns in the right order> FROM your_table_t;
-- grants on the view (the same as the table)
GRANT ** TO ** ON your_table;
Your application will behave as if the columns were in the "right" position. You don't have to touch at the physical structure.
In Oracle 12c it is now easier to rearrange columns logically. It can be achived by making column invisible/visible.If you change a invisible column to visible , the column will appear last in the odering.
Consider Using Invisible Columns
Create wxyz table:
CREATE TABLE t (
w INT,
y VARCHAR2,
z VARCHAR2,
x VARCHAR2
);
rearrange the x column to the middle:
ALTER TABLE wxyz MODIFY (y INVISIBLE, z INVISIBLE);
ALTER TABLE wxyz MODIFY (y VISIBLE, z VISIBLE);
DESCRIBE wxyz;
Name
w
x
y
z
Recreating the table (via rename/temporary table so you don't lose your data) is the only way I know of.
I don't believe it's possible to simply change the column order.
If there isn't a ton of data/columns, you could simply rename the columns in the order you want. Then just delete * from 'your table name here'. This was a good solution for me since I hadn't inserted many records yet.
You might like to access your table via a view, so you can painlessly rearrange the logical order if it's important to the application technology.
Not possible to move column in oracle. It will be created in the last position. If anyone wanted so either view needs to be created or new table need to be created
I use this all the time:
ALTER TABLE MOVE COLUMN column_name TO ordinal_position;
Related
I have situation where I need to change the order of the columns/adding new columns for existing Table in SQL Server 2008.
Existing column
MemberName
MemberAddress
Member_ID(pk)
and I want this order
Member_ID(pk)
MemberName
MemberAddress
I got the answer for the same ,
Go on SQL Server → Tools → Options → Designers → Table and Database Designers and unselect Prevent saving changes that require table re-creation
2- Open table design view and that scroll your column up and down and save your changes.
It is not possible with ALTER statement. If you wish to have the columns in a specific order, you will have to create a newtable, use INSERT INTO newtable (col-x,col-a,col-b) SELECT col-x,col-a,col-b FROM oldtable to transfer the data from the oldtable to the newtable, delete the oldtable and rename the newtable to the oldtable name.
This is not necessarily recommended because it does not matter which order the columns are in the database table. When you use a SELECT statement, you can name the columns and have them returned to you in the order that you desire.
If your table doesn't have any records you can just drop then create your table.
If it has records you can do it using your SQL Server Management Studio.
Just click your table > right click > click Design then you can now arrange the order of the columns by dragging the fields on the order that you want then click save.
Best Regards
I tried this and dont see any way of doing it.
here is my approach for it.
Right click on table and Script table for Create and have this on
one of the SQL Query window,
EXEC sp_rename 'Employee', 'Employee1' -- Original table name is Employee
Execute the Employee create script, make sure you arrange the columns in the way you need.
INSERT INTO TABLE2 SELECT * FROM TABLE1.
-- Insert into Employee select Name, Company from Employee1
DROP table Employee1.
Relying on column order is generally a bad idea in SQL. SQL is based on Relational theory where order is never guaranteed - by design. You should treat all your columns and rows as having no order and then change your queries to provide the correct results:
For Columns:
Try not to use SELECT *, but instead specify the order of columns in the select list as in: SELECT Member_ID, MemberName, MemberAddress from TableName. This will guarantee order and will ease maintenance if columns get added.
For Rows:
Row order in your result set is only guaranteed if you specify the ORDER BY clause.
If no ORDER BY clause is specified the result set may differ as the Query Plan might differ or the database pages might have changed.
Hope this helps...
This can be an issue when using Source Control and automated deployments to a shared development environment. Where I work we have a very large sample DB on our development tier to work with (a subset of our production data).
Recently I did some work to remove one column from a table and then add some extra ones on the end. I then had to undo my column removal so I re-added it on the end which means the table and all references are correct in the environment but the Source Control automated deployment will no longer work because it complains about the table definition changing.
The real problem here is that the table + indexes are ~120GB and the environment only has ~60GB free so I'll need to either:
a) Rename the existing columns which are in the wrong order, add new columns in the right order, update the data then drop the old columns
OR
b) Rename the table, create a new table with the correct order, insert to the new table from the old and delete from the old as I go along
The SSMS/TFS Schema compare option of using a temp table won't work because there isn't enough room on disc to do it.
I'm not trying to say this is the best way to go about things or that column order really matters, just that I have a scenario where it is an issue and I'm sharing the options I've thought of to fix the issue
SQL query to change the id column into first:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST;
or by using:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT AFTER 'column_name'
Not sure if this is even allowed, but if so, can someone tell me what the T-SQL is? I've tried the following but to no avail.
alter [View_Name]
alter column [Coln_Name] [New size/length] not null
GO
Any help is appreciated. Thanks!
Not directly.
This is derived automatically from the column expression. You can CAST the expression in the View SELECT list to a particular datatype though.
You would need to change the column length in the underlying table, or to change the SELECT statement forming the view to CAST or CONVERT the column to a different length data type.
Views are ways to see data in other tables; typically the data is simply whatever is in the underlying table, so you would need to change the column there.
However, you can have views that do things like cast() or convert(); these are typically a bad idea, becuase the data needs to be re-fetched every time the view is used, and these operations add overhead. In the design of the view, you can decide to cast as another data type, or do any transformation you would like - but it has overhead, and will not alter the original data.
If you know what the current view selects, you can use something like:
Alter view Viewname[cloumn] as Select cast(original_data as varchar(n)) from Original_Table
I just ran into the same situation. What I did was:
Change the column size in the table that the view looks at.
Create a script to recreate the view (if you don't already have one).
Delete the view
Use the script to recreate the view.
After that the column sizes in the view were the same as the changes I made to the underlying table.
You can not alter the column size in a view as a view is derived from other table. So if you need to change the column size, change the column size of the table. To change the column size use ALTER TABLE as :
ALTER TABLE [Table_Name]
ALTER COLUMN [Column_Name] Data_Type(Size)
After changing the column size you might need to drop the view and recreate it again.
If the length shown in the view doesn't match the underlying table then drop and recreate the view.
Use something like this to investigate the column lengths in the table and view
SELECT o.[name], *
FROM sys.all_columns c
INNER JOIN sys.objects o on o.[object_id]=c.[object_id]
WHERE c.[name] = 'OML'
-- AND c.[max_length]=11
ORDER BY O.[name];
To get the Drop and Create sql I use SSMS and right click context menu (on the view in the Object Explorer), then go to 'Script View as', and 'DROP And CREATE To'.
ALTER TABLE Log ADD log_id bigint IDENTITY BEFORE cust_id_fk
The above code adds a new column to last position. I want it to be added to the first position. Also I want to make it as Primary Key.
You would need to drop the table and recreate it with the columns in the correct order. If you make the table changes in SSMS then it can generate a change script for you which you could then use to deploy the change to a production server.
Even if the question is old, a more accurate about Management Studio would be required.
You can create the column manually or with Management Studio. But Management Studio will require to recreate the table and will result in a time out if you have too much data in it already, avoid unless the table is light.
To change the order of the columns you simply need to move them around in Management Studio. This should not require (Exceptions most likely exists) that Management Studio to recreate the table since it most likely change the ordination of the columns in the table definitions.
I've done it this way on numerous occasion with tables that I could not add columns with the GUI because of the data in them. Then moved the columns around with the GUI of Management Studio and simply saved them.
You will go from an assured time out to a few seconds of waiting.
In MSSMS select the table in the object explorer. Right click and select modify.
That will bring a new tab where you can drag the columns into a new default order.
Save and presto! Done.
Steps:
Rename the original table to tablename_temp
create a new table containing the new column
insert into tablename select * from tablename_temp
recreate foreign keys and other constraint on the new table
Short answer: It's not possible.
But you may try these steps:
Right click table name on object explorer
Click tasks
Click drop and create table
Add your columns in the position you want to add them
If you have data. Copy the data and paste it on an Excel spreadsheet, edit the spreadsheet to include new columns,edit top 100 rows and paste the data back into the table.
Goodluck
According to Change Column Order in a Table, this operation is not supported using the Transact-SQL statement.
You have to create another table and copy the data. But have a look at "ordinal position" and try to update it ?
SELECT
ORDINAL_POSITION
,COLUMN_NAME
,DATA_TYPE
,CHARACTER_MAXIMUM_LENGTH
,IS_NULLABLE
,COLUMN_DEFAULT
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'Product'
ORDER BY
ORDINAL_POSITION ASC;
Primary key is another question for which you may find lots of answers.
I would like to have a column in my DB accessible via two column names temporarily.
Why? The column name was badly chosen, I would like to refactor it. As I want my webapp to remain stable while changing the column name, it would be good to
have a (let's call it) symlink named better_column_name pointing to the column bad_column_name
change the webapplication to use better_column_name
drop the symlink and rename column to better_column_name
"Refactoring Databases" suggests to actually add a second column which is synchronized on commit in order to achieve this. I am just hoping that there might be an easier way with Oracle, with less work and less overhead.
As long as you have code that uses both column names, I don't see a way to get around the fact that you'll have two (real) columns in that table.
I would add the new column with the correct name and then create a trigger that checks which column has been modified and updates the "other" column correspondingly. So whatever is being updated, the value is synch'ed with the other column.
Once all the code that uses the old column has been migrated, remove the trigger and drop the old column.
Edit
The trigger would so do something like this:
CREATE OR REPLACE TRIGGER ...
...
UPDATE OF bad_column_name, better_column_name ON the_table
...
BEGIN
IF UPDATING ('BAD_COLUMN_NAME') THEN
:new.better_column_name = :new.bad_column_name
END IF;
IF UPDATING ('BETTER_COLUMN_NAME') THEN
:new.bad_column_name = :new.better_column_name
END IF;
END;
The order of the IF statements controls which change has a "higher priority" in case someone updated both columns at the same time.
Rename the table:
alter table mytable rename to mytable_old;
Create a view with the original tablename with both bad_column_name and better_column_name that point to the same column (and of course all the other columns):
create or replace view mytable as
select column1
, column2
, ...
, bad_column_name
, bad_column_name better_column_name
from mytable_old
;
Since this view is updatable by default (I assume here that mytable has a primary key), you can insert/update/delete from the view and it doesn't matter if you use bad_column_name or better_column_name.
After the refactoring, drop the view and rename the table and column:
drop view mytable;
alter table mytable_old rename column bad_column_name to better_column_name;
alter table mytable_old rename to mytable;
The best solution to this is only available in Oracle 11g Release 2: Edition-based Redefinition. This really cool feature allows us to maintain different versions of database tables and PL/SQL code, using special triggers and views. Find out more.
Essentially this is Oracle's built-in implementation of #AHorseWithNoName's suggestion.
you can create a view for the table. And port your application to use that view instead of the table.
create table t (bad_name varchar2(10), c2 varchar2(10));
create view vt as select bad_name AS good_name, c2 from t;
insert into vt (good_name, c2) values ('blub', 'blob');
select * from t;
select * from vt;
If you're on 11g you could look at using a virtual column. I'd probably be tempted to change the order slightly; rename the real column and create the virtual one using the old (bad) name, which can then be dropped at leisure. You may be restricted, of course, and there may be implications on other objects being invalidated that make this order less suitable for you.
When adding a column to an existing table, Oracle always puts the column at the end of the table. Is it possible to tell Oracle where it should appear in the table? If so, how?
The location of the column in the table should be unimportant (unless there are "page sizes" to consider, or whatever Oracle uses to actually store the data). What is more important to the consumer is how the results are called, i.e. the Select statement.
rename YOUR_ORIGINAL_TABLE as YOUR_NEW_TABLE;
create table YOUR_ORIGINAL_TABLE nologging /* or unrecoverable */
as
select Column1, Column2, NEW_COLUMN, Column3
from YOUR_NEW_TABLE;
Drop table YOUR_NEW_TABLE;
Select * From YOUR_ORIGINAL_TABLE; <<<<< now you will see the new column in the middle of the table.
But why would you want to do it? It's seems illogical. You should never assume column ordering and just use named column list if column order is important.
Why does the order of the columns matter? You can always alter it in your select statement?
There's an advantage to adding new columns at the end of the table. If there's code that naively does a "SELECT *" and then parses the fields in order, you won't be breaking old code by adding new columns at the end. If you add new columns in the middle of the table, then old code may be broken.
At one job, I had a DBA who was super-anal about "Never do 'SELECT *'". He insisted that you always write out the specific fields.
What I normally do is:
Rename the old table.
Create the new table with columns in the right order.
Create the constraints for that new table.
Populate with data:Insert into new_table select * from renamed table.
I don't think that this can be done without saving the data to a temporary table, dropping the table, and recreating it. On the other hand, it really shouldn't matter where the column is. As long as you specify the columns you are retrieving in your select statement, you can order them however you want.
Bear in mind that, under the tables, all the data in the table records are glued together. Adding a column to the end of a table [if it is nullable or (in later versions) not null with a default] just means a change to the table's metadata.
Adding a column in the middle would require re-writing every record in that table to add the appropriate value (or markers) for that column. In some cases, that might mean the records take up more room on the blocks and some records need to be migrated.
In short, it's a VAST amount of IO effort for a table of any real size.
You can always create a view over the table that has the columns in the preferred order and use that view in a DML statement just as you would the table
I don't believe so - SQL Server doesn't allow these either. The method I always have to use is:
Create new table that looks right (including additional column
Begin transaction
select all data from old table into new one
Drop old table
Rename new table
Commit transaction.
Not exactly pretty, but gets the job done.
No, its not possible via an "ALTER TABLE" statement. However, you could create a new table with the same definition as your current one, albeit with a different name, with the columns in the correct order in the way you want them. Copy the data into the new table. Drop the old table. Rename the new table to match the old table name.
Tom Kyte has an article on this on AskTom
link text
Apparently there's a trick involving marking the "after" columns INVISIBLE; when restored, they end up at the back.
CREATE TABLE yourtable (one NUMBER(5, 0), two NUMBER(5, 0), three NUMBER(5, 0), four NUMBER(5, 0))
ALTER TABLE yourtable ADD twopointfive NUMBER(5, 0);
ALTER TABLE yourtable MODIFY (three INVISIBLE, four INVISIBLE);
ALTER TABLE yourtable MODIFY (three VISIBLE, four VISIBLE);
https://oracle-base.com/articles/12c/invisible-columns-12cr1#invisible-columns-and-column-ordering
1) Ok so you can't do it directly. We don't need post after post saying the same thing, do we?
2) Ok so the order of columns in a table doesn't technically matter. But that's not the point, the original question simply asked if you could or couldn't be done. Don't presume that you know everybody else's requirements. Maybe they have a table with 100 columns that is currently being queried using "SELECT * ..." inside some monstrously hacked together query that they would just prefer not to try to untangle, let alone replace "*" with 100 column names. Or maybe they are just anal about the order of things and like to have related fields next to each other when browsing schema with, say SQL Developer. Maybe they are dealing with non-technical staff that won't know to look at the end of a list of 100 columns when, logically, it should be somewhere near the beginning.
Nothing is more irritating than asking an honest question and getting an answer that says: "you shouldn't be doing that". It's MY job, not YOURS! Please don't tell me how to do my job. Just help if you can. Thanks!
Ok... sorry for the rant. Now...at www.orafaq.com it suggests this workaround.
First suppose you have already run:
CREATE TABLE tab1 ( col1 NUMBER );
Now say you want to add a column named "col2", but you want them ordered "col2", "col1" when doing a "SELECT * FROM tbl1;"
The suggestion is to run:
ALTER TABLE tab1 ADD (col2 DATE);
RENAME tab1 TO tab1_old;
CREATE TABLE tab1 AS SELECT 0 AS col1, col1 AS col2 FROM tab1_old;
I found this to be incredibly misleading. First of all, you're filling "col1" with zero's so, if you had any data, then you are losing it by doing this. Secondly, it's actually renaming "col1" to "col2" and fails to mention this. So, here's my example, hopefully it's a little clearer:
Suppose you have a table that was created with the following statement:
CREATE TABLE users (first_name varchar(25), last_name varchar(25));
Now say you want to insert middle_name in between first_name and last_name. Here's one way:
ALTER TABLE users ADD middle_name varchar(25);
RENAME users TO users_tmp;
CREATE TABLE users AS SELECT first_name, middle_name, last_name FROM users_tmp;
/* and for good measure... */
DROP TABLE testusers_tmp;
Note that middle_name will default to NULL (implied by the ALTER TABLE statement). You can alternatively set a different default value in the CREATE TABLE statement like so:
CREATE TABLE users AS SELECT first_name, 'some default value' AS middle_name, last_name FROM users_tmp;
This trick could come in handy if you're adding a date field with a default of sysdate, but you want all of the existing records to have some other (e.g. earlier) date value.