I would like a single query to drop all of the views in my oracle schema. I know this isn't correct syntax (or I wouldn't be asking), but the idea that I am going for is like the following:
DROP VIEW (SELECT view_name FROM user_views);
I broke down and used a PL/SQL block like the following:
begin
for i in (select view_name from user_views) loop
execute immediate 'drop view ' || i.view_name;
end loop;
end;
If anybody knows a single query solution, I would still be curious.
You could use this query to generate the statements that you need to run (and then run the statements):
select 'drop view '||view_name||';' as statements
from all_views
where owner = 'YOUR_SCHEMA_NAME'
Be careful that you don't inadvertently remove any views in your schema that might have been created by someone other than you and which you might need, if such is possible in your particular circumstances. For example, if you use Oracle Data Miner, it stores a number of objects in your schema as you create workflows and such.
Related
Is it possible to execute a view with a stored procedure?
My procedure should first run the views (I have 2 in total) and then am combining these 2 views data into a different table for applying transformations.
Something like this:
create or replace procedure procname as
begin
here my views should get triggered and then starts my
execute immediate 'truncate table transtable';
insert
...
.....
...
exception
end;
What do you call "execute a view with stored procedure"? How are views "triggered"?
If you meant to ask whether you can create views in a procedure - then yes, you can - using execute immediate. Though, in Oracle, that's highly unusual practice. We create views first (at SQL level), use them everywhere (in SQL or PL/SQL) and that's what I'd suggest you to do.
If you ask why?, reason is simple: dynamic SQL doesn't scale, it is difficult to maintain and debug, and - if there's nothing "dynamic" in it, don't use it.
Moreover, if you reference those views later in your code (and they don't exist at time of compilation), PL/SQL procedure will fail with ORA-00942 (table or view doesn't exist) which means that the rest of your code should also be dynamic.
Nightmare at the horizon, in my opinion.
From what you posted so far, I don't see why would you insist on doing that dynamically:
create view "now" at SQL level
use them in the procedure
For a project I've been working on, I had to create 2 tables in Oracle using Tableau's Initial SQL window. I basically need to re-create them each time Tableau does an extract, so would have to drop and re-create them. Only using the 'DROP' statement works, but if the extract fails in the middle of it, then when it re-runs, the tables don't exist, thus it returns an error.
I tried to use the below code which works fine in SQL Developer, but Tableau doesn't seem to accept it.
--Searches and deletes table TABLEAU_LCC_LEAD_TIME if it exists
DECLARE
does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (does_not_exist, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE TABLEAU_DOC_LEAD_TIMES';
EXCEPTION
WHEN does_not_exist
THEN
NULL;
END;
/
Tableau returns this error
Would you know of any workaround for the "/" in Tableau Initial-SQL for Oracle?
I think use temporary table in Oracle. Not need re-created table. https://oracle-base.com/articles/misc/temporary-tables
hello everyone,
I want to create a web application using jsp,servlet and jdbc etc.
It simply create a table of name student,contains various field as information about student in database and different page perform different query tasks .
The problem is that I want to create a war file to distribute this app to my client.
When I write a sql query to create a table in my jsp page , it tries to create a new table every time whenever I run this project.
Here i want that it creates a table only when the user run this first time.So that when I distribute the war file to my client ,on the first run it create a student name table and perform the required query and for the future run it only perform other query but not create a table again.
I need your valuable guidance and overview for solving this problem.Any type of help will be appreciated.
"thanks"
In Oracle, the workaround is to wrap it in an anonymous BEGIN-END block. The EXCEPTION block would simply allow the table already exists error.
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE...
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -955 THEN
NULL; -- ignore the ORA-00955 error
ELSE
RAISE;
END IF;
END;
/
This is one way preferably. Another way would be to manually check if the table exists or not in the data dictionary view dba_tables.
SELECT count(*)
INTO variable_count
FROM dba_tables
WHERE table_name = 'table_name';
So,
IF variable_count = 0 THEN EXECUTE IMMEDIATE CREATE TABLE ...
I have a table which stores the names of certain tables - tableNames. I'd like to run a DELETE statement on some of those tables (deleting all the rows from the tables they represent, not removing them from tableNames). I thought I could just do
DELETE FROM (SELECT tableName FROM tablesNames WHERE ...) AS deleteTables
But I keep getting an incorrect syntax error. I also thought about iterating through a table in a WHILE loop and storing using a variable, but that I'm hoping there's more simpler way. Specifically, this is for Microsoft SQL
You cannot do it that way because the inner SELECT is simply another set you're deleting from.
Basically you're creating a table of table names and telling the DB to delete it. Even iterating through them won't work without dynamic sql and EXEC
Do you need to automate this process?
What I've done in the past is something like this
SELECT
'DELETE ' + tableName
FROM
tablenames
WHERE
[conditions]
your output will look like this:
DELETE myTableName1
DELETE myTableName2
DELETE myTableName3
And then simply copying the results of this query out of the window and running them.
IF you need to automate this in SQL you can concatenate all the output strings in the result and send them as a parameter to an EXEC call.
try using cursor :
DECLARE #tableName varchar(255)
DECLARE cur cursor for select tableName from tableNames where (...)
OPEN CUR
FETCH NEXT FROM cur into #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
exec('DELETE ' + #tableName)
FETCH NEXT FROM cur into #tableName
END
CLOSE cur
DEALLOCATE cur
In this respect, you can think of SQL as a compiled language like C/C++. The SQL statement is evaluated by a "compiler", and certain checks are done. One of those checks is for the existence (and permissions) for tables and columns referenced directly in the query. Exact table names must be present in your code at the time you build your query, so that the compiler can validate it.
The good news is that SQL is also a dynamic language. This means you can write a procedure to build a query as a string, and tell the database to execute that string using the EXEC command. At this point, all the same "compiler" rules apply, but since you were able to insert table names directly into your SQL string, the query will pass.
The problem is that this also has security implications. It would be a good idea to also check your table against a resource like information_schema.Tables, to avoid potential injection attacks. Unfortunately, if you're deleting whole tables your whole model may already be suspect, such that you can't guarantee that someone won't inject a table name that you really want to keep. But depending on how these are populated, you may also be just fine.
Assuming no potential constraint errors exist, one interesting possibility is an undocumented procedure sp_MSforeachtable, which will allow you to apply a given operation against all tables whose names are returned by your query:
EXEC sp_MSforeachtable #command1 = 'delete from ?'
, #whereand = 'and o.name IN (SELECT tableName FROM tablesNames WHERE ...)'
Also http://weblogs.asp.net/nunogomes/archive/2008/08/19/sql-server-undocumented-stored-procedure-sp-msforeachtable.aspx for more reading.
The delete statement works with only one table name at a time.
The full syntax is documented here, but it's TL;DR... In short, you'll have to use the loop.
I am using a similar cursor as #Pavel with a list of my indexes in order to reorganise them. Operations like this are one of the extremely few good reasons for cursors.
I'm trying to run multiple ddl statements within one Execute Immediate statement.
i thought this would be pretty straight forward but it seems i'm mistaken.
The idea is this:
declare v_cnt number;
begin
select count(*) into v_cnt from all_tables where table_name='TABLE1' and owner = 'AMS';
if v_cnt = 0 then
execute immediate 'CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL) ALTER TABLE TABLE1 ADD (MYVAL2 NVARCHAR2(10))';
end if;
end;
however this results in an error
ORA-00911: invalid character
ORA-06512: at line 10
Each of the statements within the batch run fine if i execute them by themselves. and if i take this statement and execute it, it will run fine (with the ; between the 2 statements). If i remove the ; between statements i get a different error about invalid option
the plan is that i'll be able to build a table, export the table schema for this table including all it's alter statements, and then run the batch against another system as part of an install/update process.
So, how do i batch these DDL statements within a single execute immediate? Or is there a better way to do what i'm needing?
I'm a bit of a Oracle newb, i must admit. Thank you all for your patience.
The semicolon is not part of Oracle's SQL syntax. SQL*Plus and other client side tools use semicolon to signal the end of a SQL Statement, but the server doesn't see it.
We can force SQL*Plus to pass the semicolon to the DB:
SQL> set sqlterminator off
SQL> select * from user_tables;
2 /
select * from user_tables;
*
ERROR at line 1:
ORA-00911: invalid character
If i take this statement and execute it, it will run fine (with the ; between the 2 statements) The client tool you are using, breaks it into two calls to the DB.
So, I don't think it is possible to pass multiple statements inside an execute immediate.
I suppose one could call execute immediate with a string containing an anonymous PL/SQL block, with individual calls to execute immediate inside it ... and I don't know what the point of doing that would be. ;)
Why do you need a single EXECUTE IMMEDIATE call? Surely just do it as 2 calls?
Bear in mind that each DDL statement contains an implicit COMMIT, so there's no concurency benefit to doing it as a single call.
Also, why not just set up the table correctly in the first call? You could do...
CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL, MYVAL2 NVARCHAR2(10))
...instead of needing 2 calls.
Also, have you looked at DBMS_METADATA... it can generate DDL for objects such as tables for you.