Why is my initial SQL (Oracle) not accepted by Tableau? - sql

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

Related

Oracle: 'populate pending' index of another schema

When attempting to call ctx_ddl.populate_pending on an index of another schema...
call ctx_ddl.populate_pending ('OTHERSCHEMA.INDEX_NAME', null);
... I'm getting an Oracle error:
SQL-Fehler: ORA-20000: Oracle Text error:
DRG-10502: index INDEX_NAME does not exist
When I connect as OTHERSCHEMA user and execute the same statement, everything works fine.
Why does it tell me the index doesn't exist (it does, verified) here?
Am I missing any grants or anything else?
Constraint for proposed solutions: I don't want to have to use 'alter session' as a workaround.
EDIT:
Seems to be a bug in Oracle 11.2. With Oracle 12.1, the statement works fine. Treat the solution below as a workaround for Oracle 11.2.
Solved it with a delegation to a procedure in the target schema:
On target schema 'OTHERSCHEMA'
CREATE OR REPLACE PROCEDURE POPULATE_PENDING_INDEX IS
BEGIN
execute immediate 'call ctx_ddl.populate_pending(''INDEX_NAME'', NULL)';
END;
/
Execute with another schema user:
exec OTHERSCHEMA.POPULATE_PENDING_INDEX

what is the code to create a table in sql only at first run of project?

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 ...

Oracle: DBMS_UTILITY.EXEC_DDL_STATEMENT vs EXECUTE IMMEDIATE

Which are the differences between DBMS_UTILITY.EXEC_DDL_STATEMENT and EXECUTE IMMEDIATE?
Fundamentally they do the same thing, which is to provide a mechanism to execute DDL statements in PL/SQL, which isn't supported natively. If memory serves me well, the EXEC_DDL_STATEMENT was available in the Oracle 7 version of the DBMS_UTILITY package, whereas Native Dynamic SQL (EXECUTE IMMEDIATE) was only introduced in 8.
There are a couple of differences. EXECUTE IMMEDIATE is mainly about executing dynamic SQL (as its NDS alias indicates). the fact that we can use it for DDL is by-the-by. Whereas EXEC_DDL_STATEMENT() - as the suggests - can only execute DDL.
But the DBMS_UTILITY version isn't retained just for backwards compatibility, it has one neat trick we cannot do with EXECUTE IMMEDIATE - running DDL in a distributed fashion. We can run this statement from our local database to create a table on a remote database (providing our user has the necessary privileges there):
SQL> exec DBMS_UTILITY.EXEC_DDL_STATEMENT#remote_db('create table t1 (id number)');
I'm not recommending this, just saying it can be done.
I realize I am 9 years late to the reply but there is one additional difference.
dbms_utility.exec_ddl_statement will not execute anything but DDL. If you try to do say an insert, it will not do it. It will also not return an error either so you won't know that you did not insert.
-- drop table kevtemp1;
create table kevtemp1 (a integer);
insert into kevtemp1 values (1);
commit;
begin
insert into kevtemp1 values (2);
end;
/
commit;
begin
DBMS_UTILITY.EXEC_DDL_STATEMENT('insert into kevtemp1 values (3)');
end;
/
commit;
select * from kevtemp1;

ORACLE Batching DDL statements within a Execute Immediate

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.

Simulate a table creation with SQL

Is there a standard way to simulate a table creation in a database by using SQL? I don't want the table to be created, just check if it could be created.
One way would be to create it and then delete it again.
Any other way?
Most major servers support transactional DDL, so you can do something along these lines:
begin transaction
create table Foo ...
rollback transaction
Theoretically, in case of error it should be reported back to client, but table will not be created altogether.
Depends on the SQL DBMS you're interested in. For example Postgres supports transactional DDL and the following will work:
START TRANSACTION;
CREATE TABLE ... ();
<check for error here>
ROLLBACK;
If you're using MySQL, you could create it using a transient storage engine, like MEMORY .
Really, you have to actually create it to make sure everything is OK.
Foreign key references, functions used as default or check constraints or in computed columns are not checked until execute time.
One basic method (SQL Server) is to use "SET FMTONLY ON".
Useful for checking the statement is valid, though won't tell you everything (e.g. if the table already exists).
This will succeed:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(SomeField INTEGER)')
SET FMTONLY OFF
This will not:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(dodgysyntax)')
SET FMTONLY OFF
This approach is probably more useful for SELECT statements, which is what I've used it for in the past. It doesn't actually execute the statement, but returns out the metadata.