Liquibase : Expected something between the "TABLE" keyword and the "IF" keyword - teradata

I am trying to run the below sql by liquibase and I am getting an error expected something between "TABLE" and the keyword "IF" keyword .This is for teradata database
CREATE MULTISET TABLE IF NOT EXISTS SCHEMA_NAME.TABLE_NAME, NO, FALLBACK,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO AS ( I TRIED WITHOUT "AS")
(
COL1 INTEGER,
COL1 INTEGER....ETC)
PRIMARY INDEX( COL1,COL2);

REPLACE PROCEDURE <database_name>.drop_if_exists( in_object varchar(50)) begin IF EXISTS(
SELECT 1
FROM dbc.tables
WHERE tablename = in_object
and databasename='<database_name>') THEN
CALL DBC.SysExecSQL('DROP TABLE ' || in_object);
END IF; END;
Followed by the regular create table statment.

Related

Oracle trigger to prevent specified value wrote into column

I'm working on Oracle 11g 64bit.
Say I have a table named "MyTable", I'm trying to monitoring a column named "My_Name".
When "My_Name" is going to be changed to '' (before update), I want to stop it and change "My_Name" back to old value. In other word, '' isn't a legal value for the "My_Name" column.
Here's what I did so far, no compilation error, but no effect, I can still write the '' value into "My_Name" column.
CREATE OR REPLACE TRIGGER MyTable_tracking
BEFORE INSERT OR UPDATE ON MyDB.MyTable REFERENCING NEW AS newValue OLD AS oldValue
FOR EACH ROW
DECLARE
v_old VARCHAR(20);
v_new VARCHAR(20);
BEGIN
IF INSERTING THEN
v_new:=:newValue.My_Name; --Trigger checks column 'My_Name' only
ELSIF UPDATING THEN
v_old:=:oldValue.My_Name; --Trigger checks column 'My_Name' only
v_new:=:newValue.My_Name; --Trigger checks column 'My_Name' only
--IF :newValue.My_Name='' THEN
IF LENGTH(TRIM(:newValue.My_Name))=0 THEN
:newValue.My_Name:=:oldValue.My_Name;
END IF;
END IF;
END;
How can I do this?
No need for a trigger. In Oracle an empty string '' and null are the same thing. So just define my_name as NOT NULL and you can't put null or '' in it.
SQL> create table my_table (id integer primary key, my_name varchar(20) not null);
Table created.
SQL> insert into my_table values (1, 'Arthur');
1 row created.
SQL> update my_table set my_name = '' where id = 1;
update my_table set my_name = '' where id = 1
*
ERROR at line 1:
ORA-01407: cannot update ("ARTHUR"."MY_TABLE"."MY_NAME") to NULL
SQL> insert into my_table values (2, '');
insert into my_table values (2, '')
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("ARTHUR"."MY_TABLE"."MY_NAME")
SQL>
If you can't use the most efficient solution because of external restrictions (which I find highly questionable), you can use something like this:
create or replace trigger slow_not_null_check
before insert or update on my_table
for each row
begin
if inserting and :new.my_name is null then
:new.my_name := 'No NULL allowed';
end if;
if updating and :new.my_name is null then
:new.my_name := :old.my_name;
end if;
end;
/
This will silently convert, '' to 'No NULL allowed' when inserting and will restore the previous value when updating:
insert into my_table values (1, '');
insert into my_table values (2, 'Arthur');
select * from my_table;
ID | MY_NAME
---+----------------
1 | No NULL allowed
2 | Arthur
update my_table
set my_name = ''
where id = 2;
select *
from my_table;
ID | MY_NAME
---+----------------
1 | No NULL allowed
2 | Arthur
I fixed my problem whit following code
IF INSERTING THEN
v_new:=:newValue.My_Name;
ELSIF UPDATING THEN
v_old:=:oldValue.My_Name;
v_new:=:newValue.My_Name;
--IF :newValue.My_Name='some specified value' THEN --not allow some value
--IF :newValue.My_Name='' --not working
IF :newValue.My_Name='' OR :newValue.My_Name IS NULL THEN --not allow '' or null
:newValue.My_Name:=v_old; --works
--:newValue.My_Name:=:oldValue.My_Name; --not working, use variable instead
END IF;
END IF;

How to use a bind variable in trigger body?

I'm new to PL/SQL. I'm using oracle 11g XE along with sql developer. I'm trying to create to create an after insert trigger as follows
create or replace trigger tr1
after
insert ON
employee
for each row
begin
print :new.emp_id;
end;
The employee table is as follows
create table employee
( emp_id varchar2(5) primary key,
emp_name varchar2(10),
salary number,
company varchar2(10) foreign key references companies(comp_name)
);
When I run the statement I got a 'enter binds' window for the bind variable :new. But I was confused that why do I need to enter the value for :new since it is pseudorecord. Then I entered 'employee' as the values for :new. Now I'm getting the following error.
Error(2,8): PLS-00103: Encountered the symbol "" when expecting one of the following: := . ( # % ; The symbol ":=" was substituted for "" to continue.
Your problem is not in the :new pseudorecord. The error is coming from the usage of print, which is used to print the bind variable used in successful PL/SQL block or used in an EXECUTE command. For example, you can use it this way:
VARIABLE n NUMBER
BEGIN
:n := 1;
END;
/
Then
PRINT n;
But if you want to test the value being inserted, you can use DBMS_OUTPUT.PUT_LINE like this:
create or replace trigger tr1
after
insert ON
employee
for each row
BEGIN
dbms_output.put_line(:new.emp_id);
END;
/
Enable DBMS_OUTPUT window in your SQL Developer, then run
insert into employee values(1, 'empName', 1000, 'ABC');
You'll see 1 printed out.
However, you can always test the value from the table. Because the value should be already inserted into table. You can just query.

How can drop table if table exists in oracle?

I am trying to create database by my java application using my generated schema file. In schema I have included drop query also. But I want to do some improvements for DROP QUERY. So I want to check the existence of db objects before running drop query and drop only when if it exists.
I googled for it and found some oracle link, Some link suggest following syntax and some mentioned that ORACLE does not support such syntax.
SYNTAX A:
IF EXISTS DROP TABLE TABLE_NAME
SYNTAX B:
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
I also tried following queries:-
IF EXISTS (SELECT * FROM dba_objects WHERE OBJECT_NAME = 'BBB' )
DROP TABLE [BBB]
but it was giving error:-
Error starting at line 2 in command:
DROP TABLE [BBB]
Go
Error report:
SQL Error: ORA-00903: invalid table name
00903. 00000 - "invalid table name"
*Cause:
*Action:
Error starting at line 1 in command:
IF EXISTS (SELECT * FROM dba_objects WHERE OBJECT_NAME = 'BBB' ) DROP TABLE [BBB]
Error report:
Unknown Command
I refered following links:-
https://community.oracle.com/thread/2421779?tstart=0
Please suggest me if there any other queries to drop table with condition if table exists.
Drop table with no check. If any error exists you'll never know when something went wrong.
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE my_table';
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
Or you can search in Oracle dictionary.
DECLARE
l_cnt NUMBER;
BEGIN
SELECT count(*)
INTO l_cnt
FROM user_tables
WHERE table_name = 'MY_TABLE';
IF l_cnt = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE my_table';
END IF;
END;
If you run following code you do not have to check if table exists and in case of errors (table is locked with now wait or any other you will know about it)
begin
for c1 in (select owner,table_name from dba_tables where table_name='MY_TABLE') loop
execute immediate 'drop table '||c1.owner||'.'||c1.table_name||'';
end loop;
end;
Try this : It will drop table 'table_name' if it is present .
declare
a varchar2(700) ;
begin
execute immediate ' SELECT CASE WHEN tab = 1
THEN ''DROP TABLE TABLE_NAME''
ELSE ''select 1 from dual''
END
FROM ( SELECT sum(case when table_name = ''TABLE_NAME'' then 1 else 0 end ) as tab FROM user_tables)' into a;
EXECUTE IMMEDIATE a;
end;

Inserting into table using data from two other tables, using PL/SQL on SQLDeveloper

I'm writing a PL/SQL procedure, and I need to insert into a Table, based on an equality of two columns from two differents tables.
Here is my code:
create or replace PROCEDURE insertSomething
IS
BEGIN
INSERT INTO MYDBP ( ZIP )
SELECT POSTCODE
FROM ZIPDBP
WHERE ZIPDBP.ZIP = OTHERDBP.ZIP;
COMMIT;
END;
I'm getting an error saying OTHERDBP.ZIP is an invalid identifier. What is the issue?
EDIT:
To get the output I expected I need another equality statement between two of the tables ID, but again I'm getting invalid identifier again, this time for DBP_CLIENTS.ID. Here is the code
INSERT INTO DBP_CLIENTS ( POSTCODE )
SELECT POSTCODE
FROM DBP_POSTCODE, HELENS_DATA
WHERE DBP_POSTCODE.LOCALITY = HELENS_DATA.SUBURB
AND DBP_POSTCODE.STATE = 'NSW'
AND DBP_CLIENTS.ID = HELENS_DATA.ID;
COMMIT;
Try this:
create or replace PROCEDURE insertSomething
IS
BEGIN
INSERT INTO MYDBP ( ZIP )
SELECT POSTCODE
FROM ZIPDBP, OTHERDBP
WHERE ZIPDBP.ZIP = OTHERDBP.ZIP;
COMMIT;
END;
You have to add otherdbp to from section. And you don't need to use () in procedure declaration.
Moreover, insert is reserverd word in pl/sql, so procedure must have different name
You have to add DBP_CLIENTS in the FROM clause:
INSERT INTO DBP_CLIENTS ( POSTCODE )
SELECT POSTCODE
FROM DBP_POSTCODE, HELENS_DATA, DBP_CLIENTS
WHERE DBP_POSTCODE.LOCALITY = HELENS_DATA.SUBURB
AND DBP_CLIENTS.ID = HELENS_DATA.ID
AND DBP_POSTCODE.STATE = 'NSW';
COMMIT;

Passing comma-separated value from .NET to stored procedure using the value in "IN" SQL function

I have an SQL query similar to the following:
create procedure test
(
#param1 nvarchar(max)
)
as
begin
select * from table where column1 in (#param1)
end
Now I need to pass the value of #param1 from my .net application in such a way that the above query works.
Can some one please advise me on how to pass from my VB.NET code a value which is similiar to below:
'1','2','3'
My main question is how do I structure value of parameter like above example from my .NET application?
quickly like that, I would create a table valued function that would parse it so you can do
select *
from table
where field in (select field from dbo.myfunction(#param1))
For this type of thing, I use this function and use it as follows:
select Column1, column2 from my table where ID in (select item from fnSplit('1,2,3,4,5,6',','))
create FUNCTION [dbo].[fnSplit](
#sInputList VARCHAR(8000) -- List of delimited items
, #sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
)
RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter,#sInputList,0) <> 0
BEGIN
SELECT
#sItem=RTRIM(LTRIM(SUBSTRING(#sInputList,1,CHARINDEX(#sDelimiter,#sInputList,0)-1))),
#sInputList=RTRIM(LTRIM(SUBSTRING(#sInputList,CHARINDEX(#sDelimiter,#sInputList,0)+LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List SELECT #sInputList -- Put the last item in
RETURN
END
I don't think the problem is in the values you are passing. #param1 is just a string.
You need to address this in your procedure. Your select statement will not be able to recognize the values in you IN clause. One solution is to take the comma-separated string and insert each record into a table variable Explained Here
If your table variable is table #param_list, you procedure test looks like:
create procedure test ( #param1 nvarchar(max) )
as begin
select * from table where column1 in (Select thefield from #param_list);
end

Resources