is it possible to drop and create sequence in oracle 11g - sequence

I am a newbie to sequences, I need to know that, is it possible to use if else block in sequence? To check if sequence exist drop in if block and in else block re create the same sequence.

Your question is not totally clear to me. I am trying to reply as per my understanding.
is it possible to use if else block in sequence?
If by above statement you are trying to know whether we can use if else construct inside the body of a sequence DDL, then the answer is - No, we cant. The sequence DDL has some predefined paramaters that we need to mentione while creating the sequence. If-else construct can be written inside a plsql block only and sequence DDL does not have provision to have any plsql block unlike trigger. Hence, if-else can not be mentioned inside a sequence.
To check if sequence exist drop in if block and in else block re
create the same sequence.
From the above statement it seems you are trying to know whether we can create sequence inside a plsql block, because the flow that you have mentioned above for the if-else checking can be done inside a plsql block only. The answer to that is - Yes, a sequence can be created inside plsql block using execute immediate. Please see the code below for your case -
if seq_exists then
EXECUTE IMMEDIATE('drop sequence seq');
else
EXECUTE IMMEDIATE('create sequence seq start with 1 cache 500');
end if;

Related

If we have out parameter in plsql procedure and return in function.Then why we use procedure instead of function?

If we have only Out parameter in our PLSQL procedure.Then can we use function instead of procedure as function is also able to return the value.
And if we still using procedure then we use this instead of function.
I hope I am able to convey the right question which I want to ask?
Some important difference between both are as following:
Function:
It can be called from the SQL statement (SELECT, UPDATE, DELETE)
Can return only one value
DML operations are not allowed in it
Best for selecting the value for some common complex logic.
Procedure:
It cannot be called from the SQL statement. You must need the PL/SQL block to call it.
Can return multiple values (OUT parameters)
All DML operations are allowed within procedures.
Best for doing some complex logic and updating the table data accordingly.
It depends on what the procedure does.
For example, if it (along with returning some value) uses DML operations (e.g. inserts rows into some table), then function can't do that - you'll have to use a procedure.
Procedure's drawback is that you can't use it in a SELECT statement, such as
select proc_name(out_param) from dual;
You'll have to use a function in such cases.
Also, OUT parameter has to be stored somewhere, and that's usually a locally declared variable, but that means that you need another PL/SQL block to call the procedure and see its result.
If everything your current procedure does is to find & return some value, then yes - a function might be a better choice.

Using two updates where second update statement is using column from first update statement as input

I've small doubt about update code block which has been written by someone before and now I'll be using it in my Java program.
Is it possible to update a column first, then commit and afterwards use same column as an input in another update statement inside same block, as listed in below code. I know using sub-query way to do this but have never seen this way before. It'll great if someone can confirm
1) Whether it is correct?
2) If not, what can be updated to make it work beyond using sub-query format.
3) Also, bas_capital_calc_cd is column in same table derivatives which is being updated. Can we pass column as an input to functions, such as bas2_rwa_calc here? Moreover, can we pass column name at all in plsql function as input.
Thanks in advance for help!
--BAS_EB_RWA_COMMT is being used in BAS_EB_TOTAL_CAPITAL calculation. similarly, BAS_AB_RWA_COMMT is being used in BAS_AB_TOTAL_CAPITAL calculation.
IF ID = 17 THEN
UPDATE derivatives
SET BAS_CAPITAL_CALC_CD = 'T',
BAS_CATEGORY_CD = case when nvl(rec.ssfa_resecure_flag,'N') = 'Y' then 911 else 910 end,
BAS_EB_RWA_COMMT = bas2_rwa_calc(bas_capital_calc_cd, v_SSFA_COMMT_AMT,v_BAS_CAP_FACTOR_K_COMMT, v_basel_min,v_bas_rwa_rate) + NVL(BAS_CVA_PORTFOLIO_RWA,0),
BAS_AB_RWA_COMMT = bas2_rwa_calc(bas_capital_calc_cd, v_SSFA_COMMT_AMT,V_BAS_CAP_FACTOR_K_COMMT, v_basel_min,v_bas_rwa_rate) + NVL(BAS_CVA_PORTFOLIO_RWA,0),
BAS_ICAAP_EB_RWA_COMMT = bas2_rwa_calc(bas_capital_calc_cd,bas_unused_commt,bas_icaap_factor_k_commt,v_basel_min,v_bas_rwa_rate),
WHERE AS_OF_DATE = v_currect_DATE
COMMIT;
UPDATE derivatives
SET BAS_EB_TOTAL_CAPITAL = round(BAS2_MGRL_CAPITAL(v_date, BAS_EB_RWA, BAS_EB_RWA_COMMT),2),
BAS_AB_TOTAL_CAPITAL = round(BAS2_MGRL_CAPITAL(v_date, BAS_AB_RWA, BAS_AB_RWA_COMMT),2)
WHERE AS_OF_DATE = v_DATE
AND ID_NUMBER = rec.ID_NUMBER
AND IDENTITY_CODE = rec.IDENTITY_CODE;
COMMIT;
WHERE AS_OF_DATE = v_currect_DATE;
COMMIT;
END IF
In DB2 and the SQL standard you use a feature called FINAL_TABLE to do this. In Oracle you use a statement called "RETURNING".
cf - https://blog.jooq.org/tag/final-table/
As I understood from your question statement you need to understand the PLSQL. Hoping, I got it correct.
To understand the concept let us first discuss what is a PL/SQL?
Theory Source: https://www.geeksforgeeks.org/plsql-introduction/
PL/SQL is a block structured language that enables developers to combine the power of SQL with procedural statements.All the statements of a block are passed to oracle engine all at once which increases processing speed and decreases the traffic.
Disadvantages of SQL:
SQL doesn’t provide the programmers with a technique of condition checking, looping and branching.
SQL statements are passed to Oracle engine one at a time which increases traffic and decreases speed.
SQL has no facility of error checking during manipulation of data.
Features of PL/SQL:
PL/SQL is basically a procedural language, which provides the functionality of decision making, iteration and many more features of procedural programming languages.
PL/SQL can execute a number of queries in one block using single
command.
One can create a PL/SQL unit such as procedures, functions, packages, triggers, and types, which are stored in the database for reuse by applications.
PL/SQL provides a feature to handle the exception which occurs in PL/SQL block known as exception handling block.
Applications written in PL/SQL are portable to computer hardware or operating system where Oracle is operational.
PL/SQL Offers extensive error checking.
Now please check the highlighted point PL/SQL can execute a number of queries in one block using single command.
Let us take an example of the situation you described.
create table test as select 0 as col1, 0 as col2 from dual;
declare
v_col1 test.col1%type;
v_col2 test.col2%type;
begin
update test set col1 = col1 + 1;
commit;
dbms_output.put_line('col1='+v_col1);
dbms_output.put_line('col2='+v_col2);
update test set col2 = col1 + 1;
commit;
dbms_output.put_line('col1='+v_col1);
dbms_output.put_line('col2='+v_col2);
end;
Please run above code, it is just a simple example of your question.
Ans Point 1: (Considering Oracle as sample database) So, according to me yes, it is possible, However, way you are writing these two updates, I am not sure that this is the best way or only way to handle such situations.
Ans Point 3: You can use Dynamic SQL to achieve the same in Oracle.
Reference Link : https://docs.oracle.com/cd/B10500_01/appdev.920/a96590/adg09dyn.htm

How to check updating of column value in oracle trigger

I'm using UPDATING(col_name) to check if column's value is updated or not inside the trigger. But the big problem is this command won't check value of :old and :new objects. UPDATING(col_name) is true if col_name existed in set part of query even with old value.
I don't want to check :old.col1<>:new.col1 for each column separately.
How can I check changing column value correctly?
I want to do this in a generic way. like :
SELECT col_name bulk collect INTO included_columns FROM trigger_columns where tbl_name ='name';
l_idx := included_columns.first;
while (l_idx is not null)
loop
IF UPDATING(included_columns(l_idx)) THEN
//DO STH
return;
END IF;
l_idx := included_columns.next(l_idx);
end loop;
Thanks
IN a comment you said:
"I want to do this in a generic way and manage it safer. put columns which are important to trigger in a table and don't put many IF in my trigger. "
I suspected that was what you wanted. The only way you can make that work is to use dynamic SQL to assemble and execute a PL/SQL block. That is a complicated solution, for no material benefit.
I'm afraid I laughed at your use of "safer" there. Triggers are already horrible: they make it harder to reason about what is happening in the database and can lead to unforeseen scalability issues. Don't make them worse by injecting dynamic SQL into the mix. Dynamic SQL is difficult because it turns compilation errors into runtime errors.
What is your objection to hardcoding column names and IF statements in a trigger? It's safer because the trigger is compiled. It's easier to verify the trigger logic because the code is right there.
If this is just about not wanting to type, then you can generate the trigger source from the data dictionary views (such as all_tab_cols) or even your own metadata tables if you must (i.e. trigger_columns).
You can define a global function similar to the following:
CREATE OR REPLACE FUNCTION NUMBER_HAS_CHANGED(pinVal_1 IN NUMBER,
pinVal_2 IN NUMBER)
RETURN CHAR
IS
BEGIN
IF (pinVal_1 IS NULL AND pinVal_2 IS NOT NULL) OR
(pinVal_1 IS NOT NULL AND pinVal_2 IS NULL) OR
pinVal_1 <> pinVal_2
THEN
RETURN 'Y';
ELSE
RETURN 'N';
END IF;
END NUMBER_HAS_CHANGED;
Now in your trigger you just write
IF NUMBER_HAS_CHANGED(:OLD.COL1, :NEW.COL1) = 'Y' THEN
-- whatever
END IF;
Note that this function is defined to return CHAR so it can also be called from SQL statements, if needed - for example, in a CASE expression. Remember that in Oracle, there is no BOOLEAN type in the database - only in PL/SQL.
You'll probably want to create additional versions of this function to handle VARCHAR2 and DATE values, for a start, but since it's a matter of replacing the data types and changing the name of the function I'll let you have the fun of writing them. :-)
Best of luck.

Stored Procedure delete statement after return

So I'm tracking down a potential bug in a sync process I'm in charge of (written by someone else). When viewing one of the stored procedures that is being called, I noticed something peculiar. Based on my understanding of returns, anything after the return will not be returned. However, I am not positive if this is the case in SQL. Based on the chunk of SQL below, will the delete statement ever run? Or does the SP return information to signify whether rows were deleted (such as how many rows, whether it was successful, etc.)? I am assuming this is a bug in the SP, but want to confirm before taking action. Thanks in advance.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[DeleteSalesforce_Contacts]
AS
Return
Delete From dbo.Contacts Where IsDeleted = 1
GO
The documentation is pretty clear on this:
"Exits unconditionally from a query or procedure. RETURN is immediate
and complete and can be used at any point to exit from a procedure,
batch, or statement block. Statements that follow RETURN are not
executed."
The delete statement won't be executed.
The return statement takes an optional parameter, but to use a query as value you would need to use a select in parentheses. Example:
return (select top 1 id from SomeTable)
The delete would never happen when the proc is executed.
The only time a statement after the return is ever executed when a proc is run is if it was related to a goto process and the code was sent there and bypassed the return. This kind of code sometimes used to be written before Try Catch blocks were allowed in SQL Server to do something with errors.

What is the difference between ";" and "GO" in T-SQL?

I use ADO.NET as well as the sqlcmd utility to send SQL scripts to SQL Server 2008. What is the difference between using ; and GO to separate chunks of SQL?
GO is not actually a T-SQL command. The GO command was introduced by Microsoft tools as a way to separate batch statements such as the end of a stored procedure. GO is supported by the Microsoft SQL stack tools but is not formally part of other tools.
You cannot put a GO into a string of SQL and send it as part of a ADO.NET command object as SQL itself does not understand the term. Another way to demonstrate this is with the profiler: set up some statements that use GO in Query Analyzer/Management Studio and then run the profiler when you execute. You will see they are issued as separate commands to the server.
The semi-colon is used to signify the end of a statement itself, not necessarily a whole batch.
http://msdn.microsoft.com/en-us/library/ms188037.aspx
"GO" is similar to ; in many cases, but does in fact signify the end of a batch.
Each batch is committed when the "GO" statement is called, so if you have:
SELECT * FROM table-that-does-not-exist;
SELECT * FROM good-table;
in your batch, then the good-table select will never get called because the first select will cause an error.
If you instead had:
SELECT * FROM table-that-does-not-exist
GO
SELECT * FROM good-table
GO
The first select statement still causes an error, but since the second statement is in its own batch, it will still execute.
GO has nothing to do with committing a transaction.
semicolon is a statement separator. The previous statement(s) is not necessarily executed when a semicolon is encountered.
GO
Signifies the end of a batch. Executes the previous batch of statements, as does encountering the end of the block.
GO 2
Means execute the batch that many times. I think I've used that option maybe twice in my life. Then again, I'm not a DBA by trade.
Under SQL Server TSQL (2005 - 2016) bear in mind that:
Semicolon (;) is a block terminator.
GO is a batch terminator.
Additionally, GO can be used to invoke the same DML block multiple times using the following syntax:
GO [count]
Where [count] is a positive integer that indicates how many times the TSQL block of commands preceding said GO are to be carried out over and over.
Also, unlike semicolon, GO is mandatory before a new DDL, say, when you create a new view, since a semicolon separating previous commands will trigger an error. For example:
drop view #temporary_viewGO
create view #another_view...
--> NO ERRORS
If you replaced GO with a semicolon in the previous example, it will raise the following error message:
'CREATE VIEW' must be the first statement in a query batch.
'GO' is typically used to indicate the end of a batch of SQL statements which means that you could have a begin transaction and end transaction wrapped up into a single collection of statements that could fail or succeed together.
';' is generally used to separate multiple SQL statements from one another. This is noticable in SQL scripts that need to return multiple recordsets, such as `select * from table1; select * from table2;' which would result in two separate recordsets on the client's side.
The command GO means the end of a batch.
Therefore all variables declared before GO are invalid after the GO command.
Against the semicolon does not end the batch.
If You will use a DML command in a procedure, use the semicolon instead GO.
For example:
CREATE PROCEDURE SpMyProc
#myProcParam VARCHAR(20)
AS
DECLARE #myOtherParam INT = 5
;DISABLE TRIGGER ALL ON tMyTable
UPDATE tMyTable SET myVar = #myProcParam, mySecondVar = #myOtherParam
;ENABLE TRIGGER OLL ON tMyTable
I thought the ; character separates a list of SQL commands, GO just instructs SQL Server to commit all the previous commands.