Oracle if-else query to check table exist otherwise show a message? - database

When i am running below query first time its working but after again i am going to run this query i am getting exception
Select count(*) into rec from all_tables where table_name='DefaultTable';
if(rec=1) then
CREATE TABLE DefaultTable(
Code INT NOT NULL,
Code1 INT NOT NULL,
ResultCode INT NOT NULL,
CONSTRAINT DefaultTable_PK PRIMARY KEY(Code,Code1)
);
else
PRMOPT DefaultTable Already Exist //To print in Console
end if;
Can anyone tell what i am doing wrong? and what all i am doing wrong to write the above query ?
Error starting at line 2 in command:
if(rec=1) then
Error report:
Unknown Command
Error starting at line 3 in command:
CREATE TABLE DefaultTable(
Code INT NOT NULL,
Code1 INT NOT NULL,
ResultCode INT NOT NULL,
CONSTRAINT DefaultTable_PK PRIMARY KEY(Code,Code1)
Error at Command Line:3 Column:14
Error report:
SQL Error: ORA-00955: name is already used by an existing object
00955. 00000 - "name is already used by an existing object"
*Cause:
*Action:
Error starting at line 16 in command:
else
Error report:
Unknown Command
Error starting at line 17 in command:
PRMOPT Table Already Exist
Error report:
Unknown Command
Error starting at line 18 in command:
end if
Error report:
Unknown Command

Well, as I understand the author is trying to do it in one sql query. But in Oracle you can not use IF statement in simple sql. Moreover, even if you use PL/SQL the DDL statements are not allowed to be directly invoked from PL/SQL code, so you should use dynamic SQL. I think, the following script will do what you want:
DECLARE
rec NUMBER;
BEGIN
SELECT COUNT(*) INTO rec FROM all_tables WHERE table_name='DEFAULTTABLE';
IF (rec=0) THEN
EXECUTE IMMEDIATE 'CREATE TABLE DefaultTable(
Code INT NOT NULL,
Code1 INT NOT NULL,
ResultCode INT NOT NULL,
CONSTRAINT DefaultTable_PK
PRIMARY KEY(Code,Code1,ResultCode)
)';
ELSE
dbms_output.put_line('DefaultTable Already Exist');
END IF;
END;
Please, note that in order to see the messages printed via dbms_output, you should execute:
SET SERVEROUTPUT ON;

If you read the error message you will notice it says:
ORA-00955: name is already used by an existing object
This means you are trying to create a table that already exists. That explains why it runs the first time and not any more after that.
Check the entries in all_tables and you will find that Oracle creates tablenames in uppercase. So check for 'DEFAULTTABLE'.

Related

Reporting WHICH field caused an error in the pyodbc call to SQL Server

I have a collection of python files, each of which uses a number of calls of the form:
sql_str = "exec SP_UPDATE;"
try:
cursor.execute(sql_str)
except pyodbc.OperationalError as error:
print("Connection issue. connection failure")
except pyodbc.ProgrammingError as error:
# Note this error is specific to a table and a row
log_error(cursor, __file__, '', 'SP_UPDATE', 0,
"Failure running update production table for SP_UPDATE"
"SP_UPDATE" +
"",
f'pyodbc error message: {error}')
The SP's look similar too:
CREATE PROCEDURE [].[SP_UPDATE]
#id_something [nvarchar] (500) NULL,
#d_dt_start [date] NULL,
#d_dt_end [date] NULL
...
AS
BEGIN
something
END
Now the code works - most of the time. But I'm concerned about when the code does NOT work, which is always due to bad data. This code fragment is called in a loop. I should save the row number. That's helpful. But I would really like to know which column caused the problem and report that as well, because the real dataset has anywhere from 7 to over 200 columns. Is there way to figure that out?

SP2-0552: Bind variable "NEW" not declared and END Error report - Unknown Command

I have to write a trigger for the tables I made and in insert update, I have to record a separate log table for those that are updated or inserted.
Columns in the log table will be like;
Done_process (will write update, insert)
Person (student number of the person treated)
Before (previous value for update, blank for insert)
After (new value for update, new value for insert)
This is my student_info table,
CREATE TABLE student_info (
school_id NUMBER,
id_no NUMBER NOT NULL UNIQUE,
name VARCHAR2(50) NOT NULL,
surname VARCHAR2(50) NOT NULL,
city VARCHAR2(50) NOT NULL,
birth_date DATE NOT NULL,
CONSTRAINT student_info_pk PRIMARY KEY(school_id )
);
CREATE TABLE og_log(
done_process VARCHAR2(30),
person VARCHAR2(30),
before VARCHAR2(30),
after VARCHAR2(30)
);
CREATE OR REPLACE TRIGGER og_trigger
BEFORE INSERT OR UPDATE OR DELETE ON student_info
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
ENABLE
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Insert',:new.school_id,:old.name,:new.name);
ELSIF UPDATING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Update',:new.school_id,:old.name,:new.name);
END IF;
END;
/
When I try to run the code it gave an error as follows;
> Trıgger OG_TRIGGER created.
>
>
> Error starting at line : 280 in command - ELSIF UPDATING THEN Error
> report - Unknown Command
>
> SP2-0552: Bind variable "NEW" not declared.
>
> 0 rows inserted.
>
>
> Error starting at line : 283 in command - END IF Error report -
> Unknown Command
>
> SP2-0044: For a list of known commands enter HELP and to leave enter
> EXIT.
>
> Error starting at line : 284 in command - END Error report - Unknown
> Command
I believe you are creating this trigger for learning purpose and not something a real use case because what you do in trigger doesn't really making any sense.
The trigger you have mentioned is not compiling due to syntactical problems like where v_id := 20201033.
Where clause is used to compare the value and thus you should use = instead := which is an assignment operator.
Besides this problem few points which still needs to be taken care
Give a explicit convention for creating local variables. e.g. you have created a local variable v_id and the same column is also available in student_info table. Though it is not a problem in this case but it's good practice to keep the local variable specific like let's say l_v_id.
You have used a select statement inside trigger which could leads to NO_DATA_FOUND error and you should handle it by either in the exception section or another way would be using aggregate function like max() if obviously v_id is primary key. I doubt why you need this select statement ( you could use between old and new using something like coalesce(:old.school_id,:new_schoold_id) if I understood you) but I would leave it open to you to decide and act accordingly.
Considering above points final code will be,
CREATE OR REPLACE TRIGGER og_trigger
BEFORE INSERT OR UPDATE OR DELETE ON student_info
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
ENABLE
DECLARE
BEGIN
IF INSERTING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Insert',:new.school_id,:old.city,:new.city);
ELSIF UPDATING THEN
INSERT INTO og_log(done_process, person, before, after)
VALUES ('Update',:new.school_id,:old.city,:new.city);
END IF;
END;
/
Find demo db<>fiddle
EDITED: Solving probably tool issue
I doubt the issue is with SQL Developer tool usage , however last try i would like to make,
Step1:
Drop both the tables used by issuing drop command
drop table STUDENT_INFO;
drop table og_log;
Step2:
Open another SQL worksheet using alt+F10 and do as I have shown in the following image. Please try and let me know.

Invalid object name when publishing: SQLPackage (DACFramework 15) Possible Bug

I've been struggling with this issue for most of the morning and I'm ready to suggest this is a bug in SqlPackage.exe
I extract a dacpac using the following command:
C:\"Program Files"\"Microsoft SQL Server"\150\DAC\bin\SqlPackage.exe /a:Extract /ssn:$server /sdn:$dbName /st:300 /p:CommandTimeout=300 /tf:obj\$dbName\extracted.dacpac
And publish a script using:
C:\"Program Files"\"Microsoft SQL Server"\150\DAC\bin\SqlPackage.exe /a:Script /tcs:"Server=$server`;Database=$newDbName`;Trusted_Connection=True`;Connection Timeout=300`;" /p:CommandTimeout=300 /p:ExcludeObjectType=Logins /p:ExcludeObjectType=Users /p:ExcludeObjectType=RoleMembership /p:IgnoreNotForReplication=true /p:UnmodifiableObjectWarnings=false /sf:obj\$dbName\extracted.dacpac /op:obj\$dbName\publish_script.sql
The script generates but it fails when I try to execute it with the error:
Procedure MY_FUNCTION, Line 39 Invalid object name 'MY_OTHER_FUNCTION'
If I examine the script I can see the following:
LINE 300: PRINT N'Creating [dbo].[MY_FUNCTION]...'
... More code ...
LINE 400: PRINT N'Creating [dbo].[MY_OTHER_FUNCTION]...';
I've gone as far as digging into the extracted dacpac to confirm that the model.xml is picking up the dependency MY_FUNCTION has on MY_OTHER_FUNCTION. I have also verified that this isn't a case of a circular dependency. MY_OTHER_FUNCTION is dependent on one table that was created back on LINE 100.
Why is the generated script creating them out of order?
Alright I'm certain this is a bug at this point. Steps to reproduce:
Create a new database.
Run the following creation scripts:
CREATE TABLE [dbo].[someTable]([Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL) ON [PRIMARY]
GO
CREATE FUNCTION [dbo].[someOtherFunction](#Id INT = 1) RETURNS #someResults TABLE (Id INT)
AS
BEGIN
INSERT INTO #someResults(Id)
SELECT * FROM [sqlpackagebug].[dbo].[someTable] st WHERE #Id = st.Id
RETURN;
END
GO
CREATE FUNCTION [dbo].[someFunction](#Id INT = 1) RETURNS TABLE
AS
RETURN
(
SELECT * FROM [sqlpackagebug].[dbo].someOtherFunction
)
GO
Extract the dacpac using:
C:\"Program Files"\"Microsoft SQL Server"\150\DAC\bin\SqlPackage.exe /a:Extract /ssn:$server /sdn:$dbName /st:300 /p:CommandTimeout=300 /tf:extracted.dacpac
Create a script using:
C:\"Program Files"\"Microsoft SQL Server"\150\DAC\bin\SqlPackage.exe /a:Script /tsn:$server /tdn:$newDbName /tt:300 /p:CommandTimeout=300 /sf:extracted.dacpac /op:script.sql
Look over the script and you can see that the functions are not created in the proper order. The script will fail.

How to execute dynamic SQL in .net?

I'm trying to write the SQL execute statement below. I'm getting an error in .net saying
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Invalid column name 'Survey'
There is no Survey column which is correct, but what is crazy is that it is getting that value from the #SurveyNumber variable. I think my exec code is correct, but maybe I'm not escaping the #SurveyNumber properly?
The #SurveyNumber variable contains this string "Survey - 1234"
#SurveyNumber varchar(50),
#RefIds varchar(max)
AS
Begin
exec('SELECT
Distinct
r.DRAWING,
r.[DESC],
r.REFMEMO,
r.OP_PSI,
r.MAX_PSI,
r.MAX_TEMP,
r.DESIGN,
r.CORR_RATE,
r.MIN_INSP,
r.INSP_LOC,
r.REPL_DATE,
r.LAST_INSP,
r.NEXT_INSP,
r.ALLOW_PSI,
IIf( r.[CF1] is null Or r.[CF1]='''',''Max'', IIf(r.[CF1]=''L'',''Long'',IIf(r.[CF1]=''S'',''Short'',IIf(r.[CF1]=''U'',''User'',''NA''))))AS CF1,
r.[NF2]*1000 as NF2,
r.CF2,
r.V_Last_Insp,
r.V_Next_Insp,
r.V_Concern,
r.V_Memo,
r.V_Report,
r.V_Interval,
r.Insulated,
r.AVG_NEXT_INSP,
r.AVG_REPL_DATE,
r.Scaffolding,
r.Number_Xrays,
r.MIN_RMS,
r.DRAWING_FLAG
From ref r
where r.SurveyNumber = ('+#SurveyNumber+') and r.Id In ('+#RefIds+')
ORDER BY r.NEXT_INSP asc')
End

How to install PL/CTL language into PostgreSQL database 8.1.22

Hi I am using postgresql 8.1.22, I am trying to setup postgresql auditing using the following function.
CREATE OR REPLACE FUNCTION audit.if_modified_func() RETURNS TRIGGER AS $body$
DECLARE
v_old_data TEXT;
v_new_data TEXT;
BEGIN
/* If this actually for real auditing (where you need to log EVERY action),
then you would need to use something like dblink or plperl that could log outside the transaction,
regardless of whether the transaction committed or rolled back.
*/
/* This dance with casting the NEW and OLD values to a ROW is not necessary in pg 9.0+ */
IF (TG_OP = 'UPDATE') THEN
v_old_data := ROW(OLD.*);
v_new_data := ROW(NEW.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,new_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data,v_new_data, current_query());
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
v_old_data := ROW(OLD.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,original_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_old_data, current_query());
RETURN OLD;
ELSIF (TG_OP = 'INSERT') THEN
v_new_data := ROW(NEW.*);
INSERT INTO audit.logged_actions (schema_name,table_name,user_name,action,new_data,query)
VALUES (TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,session_user::TEXT,substring(TG_OP,1,1),v_new_data, current_query());
RETURN NEW;
ELSE
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - Other action occurred: %, at %',TG_OP,now();
RETURN NULL;
END IF;
EXCEPTION
WHEN data_exception THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [DATA EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN unique_violation THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [UNIQUE] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN OTHERS THEN
RAISE WARNING '[AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
END;
$body$
LANGUAGE plpgsql
SECURITY DEFINER
But if you observe in the above function current_query() is not coming with the mentioned language plpgsql. It throws some error. When I googled I found that in order to use current_query() function PL/CTL language must be installed. I tried to install as mentioned below. It throws an error. So kindly help me how to install PL/CTL language into my database so that current_query() function should work
-bash-3.2$ createlang -d dbname pltcl
createlang: language installation failed: ERROR: could not access file "$libdir/pltcl": No such file or directory
Okay as you suggested I created that current_query() function,but this time I got some thing like this , What i did is ,
CREATE TABLE phonebook(phone VARCHAR(32), firstname VARCHAR(32), lastname VARCHAR(32), address VARCHAR(64));
CREATE TRIGGER phonebook_auditt AFTER INSERT OR UPDATE OR DELETE ON phonebook
FOR EACH ROW EXECUTE PROCEDURE audit.if_modified_func();
INSERT INTO phonebook(phone, firstname, lastname, address) VALUES('9966888200', 'John', 'Doe', 'North America');
for testing the function i created a table named phonebook and created a trigger so that the function mentioned above audit.if_modified_func() will be executed after any insert or update or delete.the row is getting inserted but I am getting a error reg the audit.if_modified_func() function .the error is as follows
WARNING: [AUDIT.IF_MODIFIED_FUNC] - UDF ERROR [OTHER] - SQLSTATE: 42703, SQLERRM: column "*" not found in data type phonebook
Query returned successfully: 1 rows affected, 10 ms execution time.
Kindly tell me what can i do to get rid of the above error.
Not sure where you found the information about current_query and pltcl. These are unrelated. The reason why you can't find pltcl is simply because you're using too old PostgreSQL. current_query() has been added to Pg in version 8.4.
Is there any particular reason why you're using such old version? It is no longer supported, and it lacks almost 8 years of added features!
If you have to use 8.1, you might want to define:
create function current_query() returns text as '
select current_query from pg_stat_activity where procpid = pg_backend_pid();
' language sql;
But it is much better idea just to upgrade.
As for edited and added second question - it's very likely that Pg 8.1 cannot use "row.*" construct. Find who wrote the original code with the "dance comments", and ask about it. Perhaps it was meant to work in newer Pgs.

Resources