How to do something like this...
alter table customer_schedule add (week_number as (TO_CHAR((SCHEDULE_DATE),'iw'))
Wherein SCHEDULE_DATE is one of the existing columns in table
This is where you need VIRTUAL COLUMN. If you are on 11g and up, you could certainly do -
alter table table_name
add (column_name [data_type] [generated always] as (column_expression) [virtual]);
In your case, it will be something like -
alter table customer_schedule add (week_number data_type generated always as (TO_CHAR((SCHEDULE_DATE),'iw') VIRTUAL)
On 9i, you cannot use virtual columns, so I'd probably go with a view:
create view customer_schedule_view as
select
c.*,
to_char(c.schedule_date, 'iw')) week_number
from
customer_schedule c;
Of course, in your forms you need then to select from the view rather from the table.
The default keyword is supposed to let you store values when there is some value missing, but due to restrictions, you cannot use a column name
A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the pseudocolumns LEVEL, PRIOR, and ROWNUM, or date constants that are not fully specified.
I think a row-level BEFORE INSERT/UPDATE trigger should do want you want to do.
Related
How can I use zeroifnull for a column in my table - Snowflake?
ZEROIFNULL is function that works on expression:
SELECT t.my_column, ZEROIFNULL(t.my_column) AS new_column_name
FROM my_table AS t;
Output:
Do you mean directly within the Table definition ?
If so, you could use a virtual column expression as so...
create or replace table my_table(my_column int,
my_column_zin int as (zeroifnull(my_column)) );
insert into my_table (my_column) values (1), (2), (3), (NULL);
select my_column,
my_column_zin,
zeroifnull(my_column) AS my_column_zin_select
from my_table;
describe table my_table;
I'm not sure I'd recommend this though. I think it's probably better practice to have a View defined on top of the table to embed any calculated column expressions, and this way you can also hide the raw untreated column unless you specifically want to include it.
create or replace view my_view
as
select zeroifnull(my_column) my_column
from my_table;
Select * from my_view;
As stated before, a dedicated column definition in the table can make the trick. However, I would also not recommend this and rather use a view instead. This allows you later to check the raw data and - for example if requirements change - adjust the computation of your column based on the initial raw data.
I'm trying to add a column named order to my table. I realize that order is a reserved word in SQL. So, how do I do it?
My command:
alter table mytable add column order integer;
I've also tried:
alter table mytable add column 'order' integer;
PostgreSQL 9.1.
Use this:
alter table mytable add column "order" integer;
But, you might want to consider using a non-reserved name instead, like sort_order or something similar that reflects what the column is used for (and isn't a reserved word).
I think you don't need "column". Plus "order" is a keyword in SQL, so you should use a different name for your column. Follow this syntax:
ALTER TABLE table_name ADD column_name datatype
Source: W3Schools
ALTER TABLE table_name
ADD COLUMN "order" integer
You are using order which is a reserved keyword you should consider renaming that to something like orders. And the problem should go away.
Is this even possible, if so how? if not then I would be happy with a way that doesn't require typing each column name one by one. My use-case is that I create a table from a query and would like to make all columns NOT NULL because I later do ORM using Slick and it is a lot nicer to have all those column types not null (and therefore non Option[X]). This is static data so the column values will not be null and won't change either.
Unlike MySQL, Postgres doesn't figure out that the originating query columns are all NOT NULL already.
I'd like to avoid in my script adding the constraint one by one and be prone to breaking the solution whenever the query schema is changed i.e.
CREATE TABLE dentistry_procedure AS SELECT * FROM ...
ALTER TABLE dentistry_procedure ALTER column * SET NOT NULL;
How?
You could use metadata table and build dynamic query:
SELECT format('ALTER TABLE %I '||STRING_AGG(format('ALTER COLUMN %I SET NOT NULL', COLUMN_NAME),CHR(13)||',')
, MIN(TABLE_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE IS_NULLABLE = 'YES'
AND TABLE_NAME = 't';
db<>Fiddle demo
There is a requirement to rename the DB tables and column names,
so all the tools/application taking data from the source will have to change their queries. The solution we are planning to implement is that for every table name change we will create a VIEW with the original table name. Easy and simple to implement. No query change required, but there are cases where a table name remains the same but a column name changes within the table, so we can't create another view (any object with the same object name).
Is there a Column Synonym kind of thing which we can propose here?
Any solutions/ideas are welcome. Requirement is to have queries containing original column names referring to the new columns in the same tables.
For example:
Table Name: DATA_TABLE
Existing Column Name: PM_DATE_TIME
New Column Name: PM_DATETIME
Existing Query select pm_Date_time from Data_Table; should refer to new column pm_Datetime
You could consider renaming your original table, and then create a View in its place providing both the old and the new column-names:
CREATE TABLE Data_Table ( pm_Date_time DATE );
ALTER TABLE Data_Table RENAME TO Data_Table_;
CREATE VIEW Data_Table AS
(
SELECT pm_Date_time,
pm_Date_time AS pm_Datetime -- Alias to provide the new column name
FROM Data_table_
);
-- You can use both the old columnn-name...
INSERT INTO Data_Table( pm_Date_time ) VALUES ( SYSDATE );
-- ... or the new one
UPDATE Data_Table SET pm_Datetime = SYSDATE;
There are things that won't work the same way as before:
-- INSERT without stating column-names will fail.
INSERT INTO Data_Table VALUES ( SYSDATE );
-- SELECT * will return both columns (should not do this anyway)
SELECT * FROM Data_Table
Once you are done with your changes drop the view and rename the table and the columns.
You'll want to add virtual columns:
ALTER TABLE Data_Table ADD pm_Date_time as (pm_Datetime);
UPDATE: Oracle (11g at least) doesn't accept this and raises "ORA-54016: Invalid column expression was specified". Please use Peter Lang's solution, where he pseudo-adds zero days:
ALTER TABLE Data_Table ADD (pm_Datetime + 0) AS pm_Date_time;
This works like a view; when accessing pm_Date_time you are really accessing pm_Datetime.
Rextester demo: http://rextester.com/NPWFEW17776
And Peter is also right in this point that you can use it in queries, but not in INSERT/columns or UPDATE/SET clauses.
This was basically touched on in the answer by Thorsten Kettner, but what your looking for is a pseudocolumn.
This solution looks a little hacky because the syntax for a pseudocolumn requires an expression. The simplest expression I can think of is the case statement below. Let me know if you can make it more simple.
ALTER TABLE <<tablename>> ADD (
<<new_column_name>> AS (
CASE
WHEN 1=1 THEN <<tablename>>.<<old_column_name>>
END)
);
This strategy basically creates a new column on the fly by evaluating the case statement and copying the value of <old_column_name> to <new_column_name>. Because you are dynamically interpolating this column there is a performance penalty vs just selecting the original column.
One gotcha here is that this will only work if you are duplicating a column once. Multiple pseudocolumns cannot contain duplicate expressions in Oracle.
we cant create a another view (any object with the same object name).
That's true within a schema. Another somewhat messy approach is to create a new user/schema with appropriate privileges and create all your views in that, with those querying the modified tables in the original schema. You could include instead-of triggers if you need to do more than query. They would only need the old columns names (as aliases), not the new ones, so inserts that don't specify the columns (which is bad, of course) would still work too.
You could also create synonyms to packages etc. in the original schema if the applications/tools call any and their specifications haven't changed. And if they have changed you can create wrapper packages in your new schema.
Then your legacy tools/applications can connect to that new schema and if it's all set up right will see things apparently as they were before. That could potentially be done by setting current_schema, perhaps through a login trigger, if the way they connect or the account they connect to can't be modified.
As the tools and applications are upgraded to work with the new table/column names they can switch back to the original schema.
I would like to be able to add columns to a table with cells who's values are computed by need at 'querytime' when (possibly) selecting over them.
Are there some established ways of doing this?
EDIT: Okay I can do without the 'add columns'. What I want is to make a select query which searches some (if they exist) rows with all needed values computed (some function) and also fills in some of the rows which does not have all needed values computed. So each query would do it's part in extending the data a bit.
(Some columns would start out as null values or similar)
I guess I'll do the extending part first and the query after
You use select expression, especially if you don't plan to store the calculation results, or they are dependant on more than one table. An example, as simple as it could be:
SELECT id, (id+1) as next_id FROM table;
What type of database are you asking for? If it is SQL Server then you can use the computed columns by using the AS syntax.
Eg:
create table Test
(
Id int identity(1,1),
col1 varchar(2) default 'NO',
col2 as col1 + ' - Why?'
)
go
insert into Test
default values
go
select * from Test
drop table Test
In the SQL world it's usually expensive to add a column to an existing table so I'd advise against it. Maybe you can manage with something like this:
SELECT OrderID,
ProductID,
UnitPrice*Quantity AS "Regular Price",
UnitPrice*Quantity-UnitPrice*Quantity*Discount AS "Price After Discount"
FROM order_details;
If you really insist on adding a new column, you could go for something like (not tested):
ALTER TABLE order_details ADD column_name datatype
UPDATE order_details SET column_name = UnitPrice+1
You basically ALTER TABLE to add the new column, then perform an UPDATE operation on all the table to set the value of the newly added column.