How to keep "*" in VIEW output clause so that columns track table changes? - sql

I'm creating an Oracle view like this :
SELECT * FROM TABLE;
When I create the view, I notice that oracle changes the view query to something like :
SELECT FIELD1, FIELD2,... FROM TABLE;
My problem is that if I change the TABLE structure, add a new field for instance, the changes are not taken into consideration in the view. I have then to recreate the view, and regrant privileges on this view to the users/roles.
Is there any way to make a view mode generic and keep it as the form of : SELECT * FROM TABLE ?
Thanks.

You cannot define a simple view that would automatically change its structure when the underlying table changes. When new columns are added, you'll need to touch the view. You'll almost certainly need to do as #GordonLinoff suggests and do a CREATE OR REPLACE when the table changes. Given that changes to tables should be rare and should involve proper change control, touching the view as part of the change should be a relatively simple step.
If you're really determined to avoid having to touch the view, there are some alternatives. I generally wouldn't recommend these because they are very likely to increase rather than decrease the complexity of maintaining your system. But if you have a third party system that is generating DDL to add columns on an unpredictable basis, maybe it makes sense.
You could create a DDL trigger that fires in response to statements that ALTER the table and that submits a job using dbms_job that re-creates the view. That's quite a few moving pieces but it's generally workable.
Alternately, instead of a view, you could create a pipelined table function that returns a variable number of columns. That's going to be really complicated but it's also pretty slick. There aren't many places that I'd feel comfortable using that approach simply because there aren't many people that can look at that code and have a chance of maintaining it. But the code is pretty slick.

The * is evaluated when the view is created, not when it is executed. In fact, Oracle compiles views for faster execution. It uses the compiled code when the view is referenced. It does not just do a text substitution into the query.
The proper syntax for changing a view is:
create or replace view v_table as
select *
from table;

I have face this same issue and created a procedure which accepts the name of the table and creates the view:
str := 'create or replace view xyz.'|| tablename_in ||'_v as select * from '|| tablename_in;
execute immediate str;
Then in Toad (not sure if you use Toad), in the schema browser, right click on the table name, and then select 'Custom Queries' --> 'Edit Custom Queries' and then have it call your procedure as:
exec view_create<ObjectList>
Then you can right click on the table name and in one click create the view as Toad will pass the name of the table into the procedure.
Also in the procedure you may want to recompile the schema, so after the view is created do:
sys.utl_recomp.recomp_parallel(4, 'XYZ');
If you develop a script of some sort which can semi automate, it makes things easy.
Hope this helps...

Related

Does /*+ENABLE_WITH_CLAUSE_MATERIALIZATION */ work inside of a view creation in vertica?

I have very complicated SQL that starts out with the WITH statement in Vertica. It fails without the materialization because of resource constraints, but runs in < 20 seconds with the materialization. Then I put it into a create view statement. It appears to lose the materialization as part of the view. That's pretty frustrating. The documentation doesn't mentioned any limitations of using it inside a view.
create view view_name as
with /*+ENABLE_WITH_CLAUSE_MATERIALIZATION */
report_quarters as
From this part of the Vertica documentation:
https://www.vertica.com/docs/10.1.x/HTML/Content/Authoring/SQLReferenceManual/Statements/CREATEVIEW.htm
CREATE VIEW
Defines a view. Views are read only, so they do not support insert, update, delete, or copy operations.
The /*+ENABLE_WITH_CLAUSE_MATERIALIZATION */ hint actually triggers a CREATE LOCAL TEMPORARY TABLE ... process in the background. And that involves not only DML, like insert, update, delete and copy, but also DDL., and that is why it is not supported at this time.
A possible way of working around this, from Version 11.0.1 on, might be to use a stored procedure that:
creates a LOCAL TEMPORARY TABLE out of the WITH clause that you want to materialize.
creates a target table, using `CREATE TABLE new AS SELECT ..FROM temp_table, etc.
The end user can call the stored procedure, then select from the newly created table.

How do you save a CREATE VIEW statement?

EDIT: This question was based on the incorrect premise that SQL VIEWS were cleared from a database when the user that created them disconnects from the server. Leaving this question in existence in case others have that assumption.
I'm trying to use views in my database, but I'm running up against an inability to save the code as a SQL Server object for repeated use.
I tried saving CREATE VIEW statements as procedures and user defined functions, but as many have answered on stack overflow, CREATE PROCEDURE and CREATE FUNCTION are incompatible with CREATE VIEW due to the only one in batch issue.
Obviously I don't want to retype my CREATE VIEW statements every time, and I'd prefer not to have to load them from text files. I must be missing something here.
You don't really "save" CREATE/ALTER statements. The create or alter statement changes the structure of the database. You can use SSMS to generate the statement again later by right clicking on the view, and choosing Script as->Create. This inspects the structure of the database and generates the statement.
The problem with this approach is your database now consists of both a structure definition(DDL) as well as its contents, the data. If you dropped/created the database to clear its data, you'd also have lost the structure. So you always need a database hanging around for the structure and back it up to ensure you don't ever lose the DDL.
Personally I would use Database Projects as part of Visual Studio and SQL Server Data Tools. This allows you to keep each View, Table, etc. as separate files, and then update the database using schema compare. The main benefit being you can separate the definition of the database from the database itself, and also source control or backup the DDL files.
If you really want to, you could create a view in a proc like this:
CREATE PROCEDURE uspCreateView AS
EXEC('CREATE VIEW... ')
Though, you'll have to escape single quotes in your view code with ''
However, I have to agree with the other comments that this seems like a strange thing to do.
Some other thoughts:
You can use sp_helptext to get the code of an existing view:
sp_helptext '<your view name here>'
Also, INFORMATION_SCHEMA.VIEWS includes a VIEW_DEFINITION column with the same code:
SELECT * FROM INFORMATION_SCHEMA.VIEWS

Just starting SQL, have no real idea what I'm doing, trouble with creating and using a view

I have recently (today) started using SQL, I have absolutely no idea what I'm doing. I made a Query.sql file and started to throw some random commands in. I highlight a SELECT and execute it to see what happens, I add a new SELECT, highlight it and see what that does.
However when I tried to create a view it had some problems. I don't really understand why but using a GO before and after it seemed to solve the problem, but now when I do a select from that view, it does not recognize it (that being said, it works, but it's highlighted with red, usually that means it should not compile).
Could someone explain in layman's terms what's going on ? And how can I resolve the SELECT * FROM METRIC_STATS issue ? (I tried encapsulating it in the same go, other goes, don't exactly know how it should even look like)
GO
CREATE VIEW METRIC_STATS ( ID, MONTH, TEMP_C, RAIN_C)
AS SELECT ID,
MONTH,
(TEMP_F - 32) * 5 /9,
RAIN_I * 0.3937
FROM STATS;
GO
SELECT * FROM METRIC_STATS;
now when I do a select from that view, it does not recognize it (that
being said, it works, but it's highlighted with red, usually that
means it should not compile).
Assuming you're using SQL Server Management Studio: you have to manually reset its view list. You can do that by right clicking Views and then Refresh.
#AlexK's suggestion would also work if it exists (in my SSMS, there's no such menu command.)
GO is the default SQL batch delimiter - most DDL statements like CREATE VIEW must be the first statement in the batch, so presumably your SQL failed because you had other statements before your CREATE VIEW.
Also, CREATE VIEW can only have a single SELECT statement, hence you need the GO after the CREATE VIEW and before you SELECT from it.
Note that once the view is created, it is 'permanent' in the database - you don't need to continually create it in order to use it? If you need to change the view, you'll need to drop it before re-creating it, or alter the existing view.
I have recently (today) started using SQL, I have absolutely no idea
what I'm doing.
I suggest you to read a book about SQL before try to use it.
http://msdn.microsoft.com/en-us/library/ms130214.aspx

Updating a table which was created by a 'AS select' command

I have created a table using a 'AS SELECT' statement.
CREATE TABLE TEST AS
SELECT ...
from (MANY TABLES)
WHERE (MANY CONDITIONS);
How do I make sure that updates on any of the table columns go onto TEST as well?
Or do I have to use a VIEW? (which I dont want to as there is a need of a trigger to be working on TEST)
Are any other options available other than using a VIEW ?
You need to create a View.
CREATE TABLE AS SELECT just make a copy of data at the moment of execution.
Look into creating the table test as a materialized view.
Triggers can be placed on these and there are various update options too.
Depending on your database system you could use a Trigger to insert the values in the other table as well. That's if you need something like near-realtime syncronization. Or you might go for a daily/weekly/... batch synchronization.
As I am not so familiar with Oracle you should look at their documentation for a detailed description.

Renaming table column and having it propagate to dependent views

If we want to change the name of MyColumnName to MyAlteredColumnName...
...and we have a SQL Server 2008 table that looks like:
MyTable
MyColumnName
and a view that references the underlying column:
CREATE VIEW MyDependentView WITH SCHEMABINDING
AS
SELECT ..., MyTable.MyColumnName
We end up following this procedure:
Dropping the View
Altering MyTable.MyColumnName to MyTable.MyAlteredColumnName
Recreating the View with a reference to MyAlteredColumnName
We do this with migrator dot net.
Is there a better way to do this? Is there T-SQL that will alter a view column name? Or any support in SQL Server 2008 for automagically tying the columns together?
Without the use of a third-party tool, this is one of the only ways to do it. You can obviously also use ALTER VIEW instead of a DROP and CREATE.
It should be noted that Red-Gate makes a tool called SQL Refactor which will automate this sort of change (no I do not work for them). I'm sure there are other similar database refactoring tools out there.
Use sp_refreshview:
EXEC sp_refreshview #viewName
If you want to refresh all your views, you'll have to iterate over a loop of them, which means dynamic SQL.
And if you layered them (a view is dependent on another view - bad), you'll have to refresh the parent first...
If it's a SELECT * view, you can call sp_refreshview, as OMG_Ponies suggested. It will recompile the view and update the column metadata appropriately. This is one area where judicious use of SELECT * could have benefits, if used appropriately within a coherent scheme.
Otherwise, you must redefine the view. Any explicit references to the old column name will now raise an error.
Ah, one more alternative:
EXEC sp_rename 'MyTable.MyColumnName', 'MyAlteredColumnName'
ALTER TABLE MyTable ADD MyColumnName AS MyAlteredColumnName
EXEC sp_rename 'MyView.MyColumnName', 'MyAlteredColumnName'
It's a hack, and it's dangerous, since the stored view definition will now be out of sync with the view metadata. And you have littered the db with superfluous computed columns.
But it will work (until you forget what you did, or someone else has to maintain the system, and things start to break mysteriously).
I use a third party tool for this, it hasn't failed me yet. It's ApexSQL Refactor, here's the how-to tutorial
How to rename a column without breaking your SQL database