DBMS_OUTPUT.PUT_LINE not printing when EXECUTE IMMEDIATE executed - database

I am checking Oracle DB status and when its not open, run open command from plsql as below and check status after restart. when even the EXECUTE IMMEDIATE 'alter database open' executed, the output from furher DBMS_OUTPUT.PUT_LINE not getting printed. I have SET SERVEROUTPUT ON and SET TERM ON at the begining of the script.
begin
select INST_ID into l_inst_id from gv$instance where instance_name=l_instname;
select open_mode,name into l_mode,l_dbname from gv$database where inst_id=l_inst_id;
select inst_id,STATUS,instance_name into l_inst,l_status,l_instname from gv$instance where inst_id=l_inst_id;
if (l_mode <> 'READ WRITE') then
if (l_mode like '%MOUNT%') then
DBMS_OUTPUT.PUT_LINE( 'ERROR: DB instance : '|| l_instname || ' is not OPEN,current status is ' || l_mode );
DBMS_OUTPUT.PUT_LINE( 'Starting the Database instance : ' || l_instname );
EXECUTE IMMEDIATE 'alter database open';
end if;
select open_mode into l_fmode from gv$database where inst_id=l_inst_id;
if (l_fmode <> 'READ WRITE') then
DBMS_OUTPUT.PUT_LINE( 'ERROR: DB instance : '|| l_instname || ' open attempted but failed. Engage DBA to review the issue');
else
DBMS_OUTPUT.PUT_LINE( 'Database open command completed succefully, current DB instance status fmode: ' || l_fmode);
end if;
else
DBMS_OUTPUT.PUT_LINE( 'Status of DB instance '|| l_instname || ' is ' || l_mode || ', No action requried ' );
END IF;
end;
/

I had to declare a bunch of variables and set one of them...but I got DBMS_OUTPUT to print.
clear screen
set serveroutput on
declare
l_inst_id integer;
l_inst integer;
l_mode varchar2(30);
l_dbname varchar2(30);
l_instname varchar2(30) := 'orclcdb';
l_status varchar2(30);
l_fmode varchar2(30);
begin
select INST_ID into l_inst_id from gv$instance where instance_name=l_instname;
select open_mode,name into l_mode,l_dbname from gv$database where inst_id=l_inst_id;
select inst_id,STATUS,instance_name into l_inst,l_status,l_instname from gv$instance where inst_id=l_inst_id;
if (l_mode <> 'READ WRITE') then
if (l_mode like '%MOUNT%') then
DBMS_OUTPUT.PUT_LINE( 'ERROR: DB instance : '|| l_instname || ' is not OPEN,current status is ' || l_mode );
DBMS_OUTPUT.PUT_LINE( 'Starting the Database instance : ' || l_instname );
-- EXECUTE IMMEDIATE 'alter database open';
end if;
select open_mode into l_fmode from gv$database where inst_id=l_inst_id;
if (l_fmode <> 'READ WRITE') then
DBMS_OUTPUT.PUT_LINE( 'ERROR: DB instance : '|| l_instname || ' open attempted but failed. Engage DBA to review the issue');
else
DBMS_OUTPUT.PUT_LINE( 'Database open command completed succefully, current DB instance status fmode: ' || l_fmode);
end if;
else
DBMS_OUTPUT.PUT_LINE( 'Status of DB instance '|| l_instname || ' is ' || l_mode || ', No action requried ' );
END IF;
end;
/
I commented out the 'alter database open' - we're here to test DBMS_OUTPUT, not alter the state of my database.
Running in SQL Developer -

Related

Object was open

I'm trying to restore a SQL Server database with Delphi. The code that I have is placed in a thread and works - meaning I manage to make the restore. The problem is that I get an error from Delphi saying that "Object is open" and the program stops, even though the restore happens successfully. Why am I getting this problem and how can I fix it? Here's the code:
This is the restore thread:
type
TThreadRestoreBackUp = class( TThread )
protected
procedure Execute(); override;
public
DataSource : TMSDataSource;
Connection : TMSConnection;
Query : TMSQuery;
var
DBName, RestorePath, dbRPath, dbRLogPath : string;
differentDB : Boolean;
end;
This is how I call the thread:
procedure TfrmCreateBackUp.btnRestoreClick(Sender: TObject);
var
RestoreBackUp : BackUpThread.TThreadRestoreBackUp;
begin
RestoreBackUp := BackUpThread.TThreadRestoreBackUp.Create(True);
RestoreBackUp.FreeOnTerminate := True;
try
RestoreBackUp.DataSource := frmMain.MSDSChanges;
RestoreBackUp.Connection := frmMain.MSConnLyubenAirport;
RestoreBackUp.Query := frmMain.MSQChanges;
RestoreBackUp.DBName := edtDBName.Text;
RestoreBackUp.DifferentDB := tcxCheckBoxNewDB.Checked;
RestoreBackUp.RestorePath := cxbeChoosePath.Text;
RestoreBackUp.Start;
except on EConvertError do
RestoreBackUp.Free;
end;
end;
And this is the Execute function of the thread, aka the code that gets run, when I call the thread:
procedure TThreadRestoreBackUp.Execute();
begin
dbRPath := 'E:\ClientDBS\';
dbRLogPath := 'E:\ClientDBS\';
Query.Connection := Connection;
DataSource.DataSet := Query;
if DifferentDB then
begin
dbRPath := dbRPath + DBName + '.mdf';
dbRLogPath := dbRLogPath + DBName + '.ldf';
Query.SQL.Text := 'USE master If DB_ID(' + QuotedStr(DBName) + ') IS NOT NULL BEGIN' +
' ALTER DATABASE [' + DBName + '] SET OFFLINE WITH ROLLBACK IMMEDIATE RESTORE DATABASE [' +
DBName + '] FROM DISK = ' +
QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ALTER DATABASE [' + DBName +
'] SET ONLINE END ELSE BEGIN RESTORE DATABASE [' + DBName + ']' +
' FROM DISK = ' + QuotedStr(RestorePath)
+ ' WITH RECOVERY, MOVE ' + QuotedStr('Test') + ' TO ' +
QuotedStr(dbRPath) + ', MOVE ' + QuotedStr('Test_log') +
' TO ' + QuotedStr(dbRLogPath) + 'END';
Query.Execute;
end
else
begin
DBName := Connection.Database;
Query.SQL.Text := 'USE master ALTER DATABASE [' + DBName +
'] SET OFFLINE WITH ROLLBACK IMMEDIATE' +
' RESTORE DATABASE [' + DBName +
'] FROM DISK = ' + QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ALTER DATABASE [' + DBName +
'] SET ONLINE';
Query.Execute;
end;
DataSource.Free;
Connection.Free;
Query.Free;
end;
Here's an explanation on how it works: I have a form in which I can choose a path from a tcxButtonEdit, which opens TOpenDialog when the button is pressed. When the path is chosen I have option to press a checkbox, which indicates whether the user wants to restore in the database used, or in a different one. Then the user can enter the name of the different database or the new database if they want to save in another database and not the original. When the button Restore is pressed the thread is called and executed. The code inside the thread sets up the things needed for the restore, like paths for the files, connection, tmsQuery and DataSource. Then if it's the checkbox is checked then the if statement receives true, and makes the restore in the different database, if not then it does it in the same.

Looking for help exiting out of loop

I have been working to replicate the Box feature of AutoSys. I came across a solution shown here (https://dba.stackexchange.com/a/161658), that works very, very well. I started to add to it, checking outcome, and added handling of another ETL solution we use.
Where, I ran into trouble, is when I realized nothing was checking if a job was valid. I want to check this in case a job name is spelled incorrectly, or if someone removes a job. I don't want to assume a job is being executed if it isn't. I added a check for valid SQL Agent Job name. This works, if the job names are valid. However, if the job name is not valid, the procedure gets stuck in a loop displaying the error message 'NO JOB' until I stop the procedure.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_start_job_sequence8]
(
#JobList JobSequenceTable READONLY
,#PrntJob VARCHAR(100) = 'Unknown_Job'
)
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
SET ANSI_PADDING ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET NUMERIC_ROUNDABORT OFF;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET ANSI_WARNINGS OFF;
---------------------************TRY BLOCK************---------------------
BEGIN TRY
BEGIN
DECLARE
#JobNumber TINYINT = 1
,#JobName VARCHAR(100)
,#IsRunning BIT
,#IsEnabled BIT
,#JOB_ID VARCHAR(60) = NULL
,#JOB_HIST_ID INT
,#JOB_STATUS VARCHAR(30)
,#JOB_STATUS_ID INT
,#esub VARCHAR(100)
,#ebdy VARCHAR(500)
,#Envt VARCHAR(4)
,#OVJOB_ID VARCHAR(60)
,#OVJOB_NAME VARCHAR(120)
,#JOB_TYPE CHAR(3)
,#epri VARCHAR(6);
--- Set server environment for emails
SELECT
#Envt = CASE WHEN ##SERVERNAME LIKE '%D%' THEN 'Dev'
WHEN ##SERVERNAME LIKE '%U%' THEN 'UAT'
WHEN ##SERVERNAME LIKE '%P%' THEN 'Prod'
WHEN ##SERVERNAME LIKE '%R%' THEN 'BCP'
ELSE ''
END
--- Set server environment for email priority
,#epri = CASE WHEN ##SERVERNAME LIKE '%D%' THEN 'Low'
WHEN ##SERVERNAME LIKE '%U%' THEN 'Normal'
WHEN ##SERVERNAME LIKE '%P%' THEN 'High'
WHEN ##SERVERNAME LIKE '%R%' THEN 'High'
ELSE ''
END;
BEGIN
WHILE (#JobNumber <= (SELECT
MAX(JobNumber)
FROM
#JobList
))
BEGIN
SELECT
#JobName = JobName
FROM
#JobList
WHERE
JobNumber = #JobNumber;
--VALID JOB?
IF NOT EXISTS(SELECT j.name FROM msdb.dbo.sysjobs_view J WITH(NOLOCK)
WHERE j.Name = #JobName)
BEGIN
PRINT 'NO JOB'
END;
ELSE
BEGIN
PRINT 'YES WE FOUND THE JOB';
--END
SELECT
#JOB_ID = job_id
FROM
msdb.dbo.sysjobs_view
WHERE
name = #JobName;
SELECT
#IsEnabled = enabled
FROM
msdb.dbo.sysjobs_view
WHERE
name = #JobName;
--- Very important step here. Ouvvi job names must start with Ouvvi
SELECT
#JOB_TYPE = CASE WHEN #JobName LIKE 'Ouvvi%'
THEN 'OVI'
ELSE 'SQL'
END;
--- Check if the job already running
SELECT
#IsRunning = dbo.fnJobStatusCheck(#JobName);
IF #IsRunning = 0
BEGIN
IF #IsEnabled = 0 --- Job is disabled error and send email
BEGIN
PRINT 'Job ' + #JobName
+ ' is disabled and cannot be started';
SET #esub = 'SQL Agent job '
+ #JobName + ' in ' + #Envt
+ ' is disabled and cannot be started';
SET #ebdy = 'SQL Agent job '
+ #JobName
+ ' was scheduled to run in box job '
+ #PrntJob + ' on server '
+ ##SERVERNAME + '. '
+ #JobName
+ ' could not start as it is disabled.'
+ CHAR(10) + CHAR(13)
+ +'The job ' + #JobName
+ ' should either be enabled, or removed from box job '
+ #PrntJob + '.';
EXEC msdb.dbo.sp_send_dbmail
--#profile_name = '',
-- #recipients = 'group#mail.com'
#recipients = 'person#mail.com',
#importance = #epri,
#subject = #esub,#body = #ebdy;
END;
ELSE ---- #IsEnabled = 1
----- Job is not running nor disabled. Split for different types
---OUVVI
BEGIN
IF #JOB_TYPE = 'OVI'
BEGIN
--PRINT 'OUVVI JOB'; --- TESTING
--- Parse Ouvvi Project ID - Used for success-failure
SET #OVJOB_ID = (SELECT
RTRIM(SUBSTRING(command,
CHARINDEX('/start/',
command) + 7,3))
FROM
msdb.dbo.sysjobsteps
WHERE
job_id = #JOB_ID
AND step_id = 1
);
--- START Ouvvi Job
EXEC msdb.dbo.sp_start_job #job_name = #JobName;
--PRINT #OVJOB_ID; --- TESTING
-- Waiting for the job to finish - Ouvvi jobs don't start immediately
WAITFOR DELAY '00:00:01';
WHILE (SELECT
1
FROM
Ouvvi.dbo.Queue
WHERE
ProjectID = #OVJOB_ID
) IS NOT NULL
BEGIN
WAITFOR DELAY '00:00:15';
IF (SELECT
1
FROM
Ouvvi.dbo.Queue
WHERE
ProjectID = #OVJOB_ID
) IS NULL
BREAK;
END;
--- Get Ouvvi Job Hist ID
SET #JOB_HIST_ID = (SELECT
Instance.ID
FROM
Ouvvi.dbo.Instance
WHERE
Instance.ProjectID = #OVJOB_ID
AND Instance.EndTime = (SELECT
MAX(EndTime)
FROM
Ouvvi.dbo.Instance
WHERE
Instance.ProjectID = #OVJOB_ID
)
);
--- Get Ouvvi Result
SET #JOB_STATUS_ID = (SELECT
ISNULL(I.Result,
9)
FROM
Ouvvi.dbo.Instance I
WHERE
I.ID = #JOB_HIST_ID
);
SET #JOB_STATUS = (SELECT
CASE
WHEN I.Result = 1
THEN 'Succeeded'
WHEN I.Result = 2
THEN 'Failed'
WHEN I.Result = 3
THEN 'Cancelled'
ELSE 'Unknown'
END
FROM
Ouvvi.dbo.Instance I
WHERE
I.ID = #JOB_HIST_ID
);
IF #JOB_STATUS_ID <> 1
BEGIN
PRINT #JobName
+ ' erred with the following status: '
+ #JOB_STATUS;
SET #esub = 'Ouvvi SQL Agent job '
+ #JobName
+ ' in ' + #Envt
+ ' erred with the following status: '
+ #JOB_STATUS;
SET #ebdy = 'An Ouvvi job, scheduled in SQL Agent '
+ #JobName
+ ' has erred with the following status: '
+ #JOB_STATUS
+ ' on server '
+ ##SERVERNAME
+ '.';
EXEC msdb.dbo.sp_send_dbmail
--#profile_name = '',
-- #recipients = 'group#mail.com'
#recipients = 'person#mail.com',
#importance = #epri,
#subject = #esub,
#body = #ebdy;
END;
END;
----Its a SQL Server Job
ELSE
BEGIN
EXEC msdb.dbo.sp_start_job #job_name = #JobName;
END;
WAITFOR DELAY '00:00:15.000';
SELECT
#IsRunning = dbo.fnJobStatusCheck(#JobName);
WHILE #IsRunning = 1
BEGIN
WAITFOR DELAY '00:00:15.000';
SELECT
#IsRunning = dbo.fnJobStatusCheck(#JobName);
END;
BEGIN
SET #JOB_HIST_ID = (SELECT
job_history_id
FROM
msdb.dbo.sysjobactivity
WHERE
job_id = #JOB_ID
AND run_requested_date = (SELECT
MAX(run_requested_date)
FROM
msdb.dbo.sysjobactivity
WHERE
job_id = #JOB_ID
)
);
SET #JOB_STATUS_ID = (SELECT
ISNULL(run_status,
9)
FROM
msdb.dbo.sysjobhistory
WHERE
instance_id = #JOB_HIST_ID
);
SET #JOB_STATUS = (SELECT
CASE
WHEN #JOB_STATUS_ID = 0
THEN 'Failed'
WHEN #JOB_STATUS_ID = 1
THEN 'Succeeded'
WHEN #JOB_STATUS_ID = 2
THEN 'Retry'
WHEN #JOB_STATUS_ID = 3
THEN 'Cancelled'
ELSE 'Unknown'
END
);
BEGIN
IF #JOB_STATUS_ID <> 1
BEGIN
PRINT #JobName
+ ' erred with the following status: '
+ #JOB_STATUS;
SET #esub = 'SQL Agent job '
+ #JobName
+ ' in ' + #Envt
+ ' erred with the following status: '
+ #JOB_STATUS;
SET #ebdy = 'SQL Agent job '
+ #JobName
+ ' erred with the following status: '
+ #JOB_STATUS
+ ' on server '
+ ##SERVERNAME
+ '.';
EXEC msdb.dbo.sp_send_dbmail
--#profile_name = '',
-- #recipients = 'group#mail.com'
#recipients = 'person#mail.com',
#importance = #epri,
#subject = #esub,
#body = #ebdy;
END;
END;
END;
END;
SET #JOB_ID = NULL;
SET #JobNumber = #JobNumber + 1;
END;
END;
END;
END;
END;
END TRY
---------------------*********************************--------------------
---------------------************CATCH BLOCK**********-------------------
BEGIN CATCH
-- Print Error Information
DECLARE #ERRORMESSAGE NVARCHAR(4000);
DECLARE #ERRORSEVERITY INT;
DECLARE #ERRORSTATE INT;
SELECT
#ERRORMESSAGE = ERROR_MESSAGE()
,#ERRORSEVERITY = ERROR_SEVERITY()
,#ERRORSTATE = ERROR_STATE();
RAISERROR (#ERRORMESSAGE, #ERRORSEVERITY, #ERRORSTATE);
-- Rollback uncommittable transactions
IF (XACT_STATE()) = -1
BEGIN
PRINT 'The transaction is in an uncommittable state.'
+ ' Rolling back transaction.';
ROLLBACK TRANSACTION;
END;
-- Inserting error related information into the Error Log table
INSERT INTO dbo.tbl_Object_ErrorLog
(ObjectName
,ErrorNumber
,ErrorMessage
,ErrorSeverity
,ErrorState
,ErrorlINE
,SystemUser
,LogDate
)
SELECT
ERROR_PROCEDURE()
,ERROR_NUMBER()
,ERROR_MESSAGE()
,ERROR_SEVERITY()
,ERROR_STATE()
,ERROR_LINE()
,SYSTEM_USER
,GETDATE();
END CATCH;
---------------------********************************----------------------
END;
GO
Code to launch the procedure:
SET ANSI_WARNINGS OFF
GO
DECLARE #JobList AS JobSequenceTable
INSERT INTO #JobList
VALUES
('x_test3')
,('NoJobHere')
,('x_test1')
EXEC dba.dbo.usp_start_job_sequence8 #JobList, 'TESTING'
What I want to happen is: when it checks for valid job name, prints NO JOB and ends, it should go to line 378, add 1 to #JobNumber, end that round, going to the next job.
I can't figure out why it's stuck in the loop.
Thanks for any help.
As your loop is very long with nested blocks and hard to debug, I would do the following:
- before jumping in the loop, validate which jobs are missing
- create a table that holds the missing jobs, e.g. #MissingJobs, and do your stuff with them before you do with the existing jobs
- based on #MissingJobs remove the missing jobs from the #JobList table and then loop through those, so in this case no need to debug the long loop block. Or create a new table if you need the original and use that in the loop - but in that case more work to change everywhere from #JobList to the new one. You can get back the original list if you UNION ALL the reduced #JobList with #MissingJobs. Anyway you do, you need to remove the block after --VALID JOB? (till PRINT 'YES WE FOUND THE JOB';) as you can PRINT those out based on this logic - in this case you must also remove an END after SET #JobNumber = #JobNumber + 1; because you remove an unclosed ELSE BEGIN.

Run a migration script where a column is created and then updated

I have this script where I want to add a SurveyId and remove a ContractId from the SOR table.
However the script will not run because the SurveyId is created in the script and is considered to be an invalid column as it does not exist before it is created.
So how do I fix this?
See
-- Start of script
PRINT 'Start of script'
IF NOT EXISTS ( SELECT 1
FROM information_schema.COLUMNS
WHERE table_schema = 'dbo'
AND TABLE_NAME = 'Sor'
AND column_Name = 'ContractId' )
BEGIN
PRINT 'The colmun ContractId does not exist in Sor table'
GOTO EndScript
END
BEGIN TRANSACTION
GO
IF ##ERROR <> 0
BEGIN
GOTO ErrorScript
END
PRINT 'Begin Transaction'
-- Add the new SurveyId field to both Questions and SOR
IF EXISTS ( SELECT 1
FROM information_schema.COLUMNS
WHERE table_schema = 'dbo'
AND TABLE_NAME = 'Sor'
AND column_Name = 'SurveyId' )
BEGIN
PRINT 'The colmun SurveyId already exists in Sor table'
GOTO RemoveUnwantedData
END
ALTER TABLE [dbo].[Sor]
ADD SurveyId int null
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + '. Failed to add SurveyId column to the Sor table.'
GOTO ErrorScript
END
PRINT 'SurveyId column successfully added to the Sor table'
RemoveUnwantedData:
-- Remove ContractId = 0 - invalid rows
DELETE FROM [dbo].[Sor]
WHERE ContractId = 0
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + '. Failed to delete ContractId = 0 in the Sor table.'
GOTO ErrorScript
END
PRINT 'Removed rows in Sor where ContractId = 0, if there are any'
-- Create a query to populate the SurveyId
UPDATE [dbo].[Sor]
SET SurveyId = vw.SurveyId -- **<----ERROR HERE!!!!!!!! --**
FROM dbo.FirstSurveyIdForContractId vw WHERE vw.ContractId = dbo.Sor.ContractId
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + '. Failed to populate SurveyId in the Sor table.'
GOTO ErrorScript
END
PRINT 'SurveyIds successfully populated in the Sor table'
-- Check if SurveyId can be made not null
DECLARE #NumberOfNullEntriesSors INT
SELECT #NumberOfNullEntriesSors = COUNT(*) FROM [dbo].[Sor] WHERE SurveyId IS NULL
IF #NumberOfNullEntriesSors > 0
BEGIN
PRINT 'There are ' + CAST(#NumberOfNullEntriesSors as VARCHAR(10)) + ' SurveyIds for SORs not set, check the data before proceeding'
GOTO EndScript
END
PRINT 'All SurveyIds set and now SurveyId can be made not null.'
-- Alter SurveyId to not null
ALTER TABLE [dbo].[Sor]
ALTER COLUMN SurveyId int NOT NULL
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + ' Failed to set SurveyId for Sor table to not null'
GOTO ErrorScript
END
PRINT 'SurveyId now not null'
-- Create new foreign key relationships for SurveyId
ALTER TABLE [dbo].[Sor] ADD CONSTRAINT [FK_Sor_Survey]
FOREIGN KEY ([SurveyId]) REFERENCES [dbo].[Survey] ([ID])
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + ' Failed to set foreign key SurveyId for Sor table.'
GOTO ErrorScript
END
PRINT 'Foreign key relationships set for Sor tables on SurveyId'
-- Remove the ContractId column
ALTER TABLE [dbo].[Sor]
DROP COLUMN ContractId
IF ##ERROR <> 0
BEGIN
PRINT 'Error: ' + CAST(##ERROR AS VARCHAR(10)) + ' Failed to drop ContractId column from Sor table.'
GOTO ErrorScript
END
PRINT 'ContractId column dropped from SOR tables'
GOTO SuccessScript
ErrorScript:
PRINT 'ErrorScript Started'
ROLLBACK TRANSACTION
PRINT 'ErrorScript Completed'
GOTO Endscript
SuccessScript:
Print 'SuccessScript Started'
COMMIT TRANSACTION
PRINT 'SuccessScript Completed'
EndScript:
Print 'End of Script'
Use GO after the ALTER TABLE statement and before the UPDATE statement.
Signals the end of a batch of Transact-SQL statements to the SQL
Server utilities.
Also, because a transaction cannot span more than 1 batch, you need to break your transaction up into 2 transactions. An alternative to using GOTO for error handling in this situation is to use TRY/CATCH for each transaction as follows:
-- first batch
BEGIN TRANSACTION;
BEGIN TRY
...
ALTER TABLE [dbo].[Sor]
ADD SurveyId int null
...
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
GO
-- second batch
BEGIN TRANSACTION;
BEGIN TRY
...
UPDATE [dbo].[Sor]
SET SurveyId = vw.SurveyId -- **<----ERROR HERE!!!!!!!! --**
FROM dbo.FirstSurveyIdForContractId vw WHERE vw.ContractId = dbo.Sor.ContractId
...
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
GO

How to convert procedure from SQL Server into Oracle?

I am newbie to Oracle. I want to convert a procedure from SQL Server.
This is my procedure
ALTER PROCEDURE [dbo].[GETMONITORING]
#namabarang varchar (max)=null,
#PeriodeAwal varchar (max)=null,
#PeriodeAkhir varchar (max)=null,
#JenisLayanan varchar (max)=null
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#nWhere varchar(4000),
#Select varchar(4000),
#from varchar(4000),
#Where varchar(4000),
#final varchar (4000)
SET #Select = 'select * '
SET #from = 'from table '
SET #where = 'where 1=1'
IF isnull(len(#namabarang), 0) <> 0
SET #where = ISNULL(#where, '') + ' and namabarang like ''' + ISNULL(#namabarang, '') + ''' '
IF isnull(len(#JenisLayanan), 0) <> 0
SET #where = ISNULL(#where, '') + 'and jenislayananid like ''' + ISNULL(#JenisLayanan, '') + ''' '
IF isnull(len(#PeriodeAwal), 0) <> 0 and isnull(len(#PeriodeAkhir), 0) <> 0
SET #where = ISNULL(#where, '') + ' and tanggalpermohonan between ' + #PeriodeAwal + ' and ' + #PeriodeAkhir
SET #final = #Select + #from + #where
execute (#final)
END
I have tried to convert to Oracle. This is my stored procedure in Oracle
create or replace PROCEDURE GETMONITORING
(
v_namabarang in varchar2 default null,
v_JenisLayanan in varchar2 default null
)
AS
v_where VARCHAR2(200);
v_Select VARCHAR2(200);
v_from VARCHAR2(200);
v_final VARCHAR2(200);
v_result VARCHAR2(200);
BEGIN
v_Select := 'select * ';
v_from := 'from permohonan ';
v_where := 'where sysdate=sysdate ';
if namabarang is not null
then v_where := v_where || ' and namabarang like '%' || v_namabarang || '%'';
if jenislayanan is not null
then v_where := v_where || 'and jenislayanan='||v_jenislayanan ;
v_final := v_select || v_from || v_where;
EXECUTE immediate v_final INTO v_result;
dbms_output.put_line(v_result);
END;
When I compile that stored procedure, I get an error:
Error(37,50): PLS-00103: Encountered the symbol "%" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || member submultiset
Could you help me to fix this ?
Is my stored procedure in Oracle correct in logic?
How do I call that stored procedure in sqlplus ?
Thanks
You are missing the extra single quotes around the constants:
if namabarang is not null then
v_where :=v_where || ' and namabarang like ''%' || v_namabarang || '%';
end if;
if jenislayanan is not null then
v_where :=v_where || ' and jenislayanan = '''|| v_jenislayanan || '''';
end if;

Copying data from one database to another through Stored procedure taking long time

There are stored procedures written to copy data from one database and insert into different database. but currently the procedures taking so much time for the process to complete. Why is this happening and how to reduce the running time for procedures?
My code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [PPA].[SP_LOAD_PR_FROM_PEOPLESOFT]
#success BIT OUTPUT
AS
--//Declaring the variables
DECLARE #MessageDescription VARCHAR(200)
DECLARE #Message VARCHAR(1000)
DECLARE #REQ_ID VARCHAR(10)
DECLARE #BUSINESS_UNIT CHAR(5)
DECLARE #CURRENCY_CD CHAR(3)
DECLARE #CNT_REQUESTS NUMERIC
DECLARE #REVISION_NUMBER NUMERIC(18,0)
DECLARE #PS_DATE_MODIFIED DATETIME
DECLARE #PPA_DATE_MODIFIED DATETIME
DECLARE #REQUEST_STATUS_CODE NUMERIC(18,0)
DECLARE #REQUEST_ID NUMERIC(38,0)
DECLARE #PS_DATE_CREATED DATETIME
BEGIN
SET #success = 0
SET #MessageDescription = 'Stored procedure SP_LOAD_PR_FROM_PEOPLESOFT '
PRINT 'Inside ' + #MessageDescription
--//DECLARE the CURSOR to retrieve approved PRs from PeopleSoft's table PS_REQ_HDR
DECLARE cursor_ps_req_hdr CURSOR READ_ONLY FOR
SELECT
BUSINESS_UNIT,
LTRIM(RTRIM(REQ_ID)) AS REQ_ID,
CURRENCY_CD,
LAST_DTTM_UPDATE, ---- get PR UPDATION date time :to address issue C_42
REQ_DT ---- get PR CREATION date time :to address issue C_42
FROM PPA_PS_DAILY.PPA.PS_REQ_HDR
WHERE REQ_STATUS IN ('P', 'A')
AND HOLD_STATUS = 'N'
AND BUSINESS_UNIT IN ('GLPO1', 'ILPO1', 'INPO1', 'SOPO1', 'SSPO1' ,'TSPO1','USPO1','AUPO1','CNPO1','FRPO1','SCPO1','UKPO2','SIPO1')
ORDER BY BUSINESS_UNIT, REQ_ID
OPEN cursor_ps_req_hdr
------------------------------------------
PRINT 'Count of rows before fetching in cursor cursor_ps_req_hdr : '+cast(##cursor_rows as varchar)
------------------------------------------
FETCH NEXT FROM cursor_ps_req_hdr INTO
#BUSINESS_UNIT,
#REQ_ID,
#CURRENCY_CD,
#PS_DATE_MODIFIED, -- to address issue C_42
#PS_DATE_CREATED -- to address issue C_42
--//Check ##FETCH_STATUS to see if there are any records to retrieve.
IF ##FETCH_STATUS <> 0
BEGIN
--//No approved PRs exist in table PS_REQ_HDR
SET #Message = #MessageDescription + ': No approved PRs to retrieve from table PS_REQ_HDR.'
PRINT #Message
--//log message in a log file
END
WHILE ##FETCH_STATUS = 0
BEGIN
--Check if retrieved PR has associated request in PPA
SELECT #CNT_REQUESTS = COUNT(*)
FROM PPA.REQUEST REQ
WHERE REQ.PR_NUMBER = #REQ_ID
AND REQ.BUYER_COMPANY_ID = #BUSINESS_UNIT
IF #CNT_REQUESTS = 0 --If no associated request exists for a PR
BEGIN
SET #REVISION_NUMBER = 0 -- to address issue C_42
--insert new request and its line items into PPA back end
EXEC PPA.SP_INSERT_REQUEST #REQ_ID, #BUSINESS_UNIT, #CURRENCY_CD,#REVISION_NUMBER,#PS_DATE_CREATED,#PS_DATE_MODIFIED,#success --Added #REVISION_NUMBER,#PS_DATE_CREATED,#PS_DATE_MODIFIED :to address issue C_42
IF #success = 0
BEGIN
SET #Message = #MessageDescription + ': Failed to INSERT request and/or its line items into PPA back-end for REQ_ID = ' + #REQ_ID + ' BUSINESS_UNIT = ' + #BUSINESS_UNIT
END
END
ELSE --If associated request exists for a PR in PPA
BEGIN
-----------------------------------------------addressing issue C_42: Start---------------------------------------------------------------------
--Check request status and find
PS_DATE_MODIFIED,REQUEST_ID,REVISION_NUMBER for the request at PPA end
SELECT TOP 1 #REQUEST_ID=REQ.REQUEST_ID,#REQUEST_STATUS_CODE=REQ.REQUEST_STATUS_CODE,
#REVISION_NUMBER = REQ.REVISION_NUMBER,#PPA_DATE_MODIFIED = REQ.PS_DATE_MODIFIED
FROM PPA.REQUEST REQ
WHERE REQ.PR_NUMBER = #REQ_ID
AND REQ.BUYER_COMPANY_ID = #BUSINESS_UNIT
ORDER BY REQ.REVISION_NUMBER DESC,REQ.DATE_CREATED DESC
--Check if there is any difference in modified dates at PS and PPA end
IF #PS_DATE_MODIFIED!=#PPA_DATE_MODIFIED
BEGIN
SET #Message = #MessageDescription + ' : Request status code for REQUEST_ID '+CAST(#REQUEST_ID AS VARCHAR)+' REQ_ID = ' + #REQ_ID + ' BUSINESS_UNIT = ' + #BUSINESS_UNIT+' is '+CAST(#REQUEST_STATUS_CODE AS VARCHAR)
PRINT #Message
--Check if request at PPA end has request status code other than 10(incomplete)
IF #REQUEST_STATUS_CODE <> 10
BEGIN
SET #REVISION_NUMBER = #REVISION_NUMBER+1
--insert new request and its line items into PPA back end with next revision number
EXEC PPA.SP_INSERT_REQUEST #REQ_ID, #BUSINESS_UNIT, #CURRENCY_CD,#REVISION_NUMBER,#PS_DATE_CREATED,#PS_DATE_MODIFIED,#success --Added #REVISION_NUMBER,#PS_DATE_CREATED,#PS_DATE_MODIFIED :to address issue C_42
IF #success = 0
BEGIN
SET #Message = #MessageDescription + ': Failed to INSERT request and/or its line items into PPA back-end for REQ_ID = ' + #REQ_ID + ' BUSINESS_UNIT = ' + #BUSINESS_UNIT
PRINT #Message
END
END
ELSE -- Process the PR if request_status is incomplete i.e.(request_status_code=10)
BEGIN
--Update the PR into PPA back end
EXEC PPA.SP_UPDATE_ITEMS_OF_PR #REQ_ID, #BUSINESS_UNIT, #CURRENCY_CD,#REVISION_NUMBER,#REQUEST_ID,#PS_DATE_MODIFIED,#PS_DATE_CREATED, #success
IF #success = 0
BEGIN
SET #Message = #MessageDescription + ': Failed to UPDATE request into PPA back-end for PR_NUMBER = ' + #REQ_ID + ' BUSINESS_UNIT = ' + #BUSINESS_UNIT
PRINT #Message
END
END
END
-- Updated by Kunal, Calling to update PR items regardless of the state of the request
if(select count(*) from PPA.REQ_LINE_ITEM_PRODUCT rli,PPA.REQUEST req where rli.REQUEST_ID=req.REQUEST_ID and req.PR_NUMBER=#REQ_ID and req.BUYER_COMPANY_ID=#BUSINESS_UNIT and rli.DELETION_MARK=1)>0
begin
print 'reached to Kunals call for the proc update items'
EXEC PPA.SP_UPDATE_ITEMS_OF_PR #REQ_ID, #BUSINESS_UNIT, #CURRENCY_CD,#REVISION_NUMBER,#REQUEST_ID,#PS_DATE_MODIFIED,#PS_DATE_CREATED, #success
end
END
-----------------------------------------------addressing issue C_42:End-------------------------------------------------------------------------
--Retrieve comments from PeopleSoft and attempt inserting them into PPA's tables
SET #success = 1
EXEC PPA.SP_INSERT_COMMENTS #REQ_ID, #BUSINESS_UNIT, #success
IF #success = 0
BEGIN
SET #Message = #MessageDescription + ': Failed to INSERT comments into PPA back-end for PR_NUMBER = ' + #REQ_ID + ' BUSINESS_UNIT = ' + #BUSINESS_UNIT
PRINT #Message
END
FETCH NEXT FROM cursor_ps_req_hdr INTO
#BUSINESS_UNIT,
#REQ_ID,
#CURRENCY_CD,
#PS_DATE_MODIFIED, -- to address issue C_42
#PS_DATE_CREATED -- to address issue C_42
END
--//Close and Deallocate the cursor
CLOSE cursor_ps_req_hdr
DEALLOCATE cursor_ps_req_hdr
PRINT #MessageDescription + ': Closed and Deallocated CURSOR cursor_ps_req_hdr'
SET #success = 1
PRINT 'Successfully exiting ' + #MessageDescription
RETURN #success
ERRORHANDLER:
PRINT #MessageDescription + ': Inside ERRORHANDLER'
IF CURSOR_STATUS('global', 'cursor_ps_req_hdr') >= 0
BEGIN
CLOSE cursor_ps_req_hdr
DEALLOCATE cursor_ps_req_hdr
PRINT #MessageDescription + ': Closed and Deallocated CURSOR cursor_ps_req_hdr'
END
SET #success = 0
--//log the message in a log file if #MessageDesc <> NULL
PRINT 'Exiting ERRORHANDLER of ' + #MessageDescription
RETURN #success
END
How to improve the performance:
Remove the cursor & RBAR (row-by-agonizing-row) style coding
If you can't remove the cursor, change it at least to fast_forward and local
There's 5 calls to different procedures. Without any details about them, they could be the reason and might need tuning
Look at execution plan & statistics io output. Focus on the operations with highest IO and scans causing lot of IO, expensive sorts, spools, key lookups with a lot of executions
Remove prints
Get someone more experienced to help you

Resources