Oracle/PLSQL performance tips - oracle

I living problem in my query. When i add ROUND and DECODE query takes too long time but when i delete directly return value. When i search for sql advice no any advice. How i can fix this 2 syntax ?
SELECT I.*,
Q.INVOICE_DATE,
Q.SERIES_ID IFS_SERIES_ID,
Q.INVOICE_NO,
Q.IDENTITY,
Q.IDENTITY_NAME,
Q.ASSOCIATION_NO,
Q.NET_CURR_AMOUNT,
Q.VAT_CURR_AMOUNT,
Q.TOTAL_CURR_AMOUNT,
Q.CURRENCY_CODE,
ROUND(Q.CURR_RATE,:"SYS_B_0") CURR_RATE,
Q.PROFILE_ID DEFAULT_PROFILE_ID,
X.XML_CONTENT,
DECODE(NVL(DBMS_LOB.INSTR(X.XML_CONTENT,:"SYS_B_1",:"SYS_B_2",:"SYS_B_3"), :"SYS_B_4"), :"SYS_B_5",:"SYS_B_6", :"SYS_B_7") SINGED_UBL,
X.SCHEMATRON_RESULT,
q.SHIPMENT_ID,
APP.TBN_UTILITY_API.GET_NUMBER(I.COMPANY, I.INVOICE_ID) DESPATCH_REFERENCE,
X.OBJID XML_OBJID,
X.OBJVERSION XML_OBJVERSION,
APP.API_MODULE.GET_DESC(I.MODULE_ID) MODULE_NAME
FROM APP.TREF_INVOICE I,
APP.TREF_INVOICE_INFO_QRY Q,
APP.TREF_XML_ARCHIVE X
WHERE Q.COMPANY = I.COMPANY
AND Q.INVOICE_ID = I.INVOICE_ID
AND X.XML_ARCHIVE_ID(+) = I.XML_ARCHIVE_ID
AND I.COMPANY = :COMPANY
AND I.INVOICE_ID = :INVOICE_ID

You should trace one or more executions of each statement to see exactly what it does. When you profile the trace data you will know what to do.
SQL> select value from v$diag_info where name = 'Default Trace File'/* name of the trace file */;
SQL> exec dbms_monitor.session_trace_enable(null, null, true, false, 'all_executions')
SQL> your query executed under normal circumstances
SQL> exec dbms_monitor.session_trace_disable(null, null)

Related

ODP.NET, Managed reading LONG column results in ORA-01009

I'm trying to get the source of a view in my .net app.
To do this, I query DBA_VIEWS: it has a column TEXT with exactly what I need. The type is LONG.
If I do it using the Unmanaged driver, everything works as expected.
The same code with Managed driver results in ORA-01009: missing mandatory parameter.
Adding a transaction around the command and using breakpoint and "slow" steps sometimes results in the same code working.
ODP.NET version is 19, Oracle DB is 18c Express Edition. Strangely enough, the same code works just fine with Oracle Database 12c regardless of driver type.
Is there maybe some setting I need to change on the database or in code? I'm completely lost here.
Code I'm using for testing:
Imports System.Data.Common
Imports Oracle.ManagedDataAccess
'Imports Oracle.DataAccess
Module Views
Function CreateCommand(Connection As DbConnection) As System.Data.Common.DbCommand
Dim cmd As Data.Common.DbCommand = Connection.CreateCommand()
With CType(cmd, Client.OracleCommand)
.BindByName = True
.FetchSize = &H100000 '1 Mb
.InitialLONGFetchSize = -1 'the entire LONG or LONG RAW data is prefetched and stored in the fetch array.
.InitialLOBFetchSize = -1 'the entire LOB data is prefetched and stored in the fetch array.
End With
Return cmd
End Function
Sub query()
Try
Using DBConnection = New Client.OracleConnection("User ID=TESTUSER;Password=TESTPWD;Data Source=TESTDB;Pooling=True")
DBConnection.Open()
Using DBConnection.BeginTransaction()
Using cmdSQL = CType(CreateCommand(DBConnection), Client.OracleCommand)
cmdSQL.CommandText = "select TEXT from DBA_VIEWS where VIEW_NAME = :0"
Dim p = cmdSQL.CreateParameter()
p.ParameterName = "0"
p.Value = "TEST_VIEW"
cmdSQL.Parameters.Add(p)
Dim sw = Stopwatch.StartNew
Using rdr = cmdSQL.ExecuteReader
rdr.FetchSize = 2 ^ 20
While rdr.Read
Dim row(rdr.FieldCount - 1) As Object
rdr.GetProviderSpecificValues(row)
Dim x = row(0)
Console.WriteLine($"{x.ToString.Length} bytes")
End While
End Using
Console.WriteLine($"{sw.ElapsedMilliseconds} ms")
End Using
End Using
End Using
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Module
You can use an anonymous block with output parameter and a call to ExecuteNonQuery. Your command text will be
"begin select TEXT into :0 from DBA_VIEWS where VIEW_NAME = :1; end;"
Add 2 parameters. Make sure that
' Parameter #1 has
p.Direction = ParameterDirection.Output
p.OracleDbType = OracleDbType.Long
p.Size = 1000000
And use command cmd.ExecuteNonQuery(). Then, when parameter is retrieved, just use its value
Dim txt As String = cmd.Parametersp[0].Value.ToString()
It's a pity, Oracle deprecated LONG data type for ages but LONG data is still used many times for internal data.
You could write a function and then get the data by calling the function:
create or replace function GetViewText(v in varchar2) return clob is
ret CLOB;
BEGIN
FOR aRow IN (SELECT TEXT FROM DBA_VIEWS WHERE VIEW_NAME = v) LOOP
ret := aRow.TEXT;
-- or ret := TO_CLOB(aRow.TEXT);
END LOOP;
RETURN ret;
END;
Yet another way from this answer is to (ab)use dbms_xmlgen.getxml.
We can either use it to query a single view's code (as in my original question)
with input as (
select
:0 as VIEW_NAME
from dual
)
SELECT
substr(
text_xml,
instr(text_xml, '<LONGCOL>') + length('<LONGCOL>'),
instr(text_xml, '</LONGCOL>', -1) - (instr(text_xml, '<LONGCOL>') + length('<LONGCOL>'))
) as TEXT
from
(
-- getxml can return malformed xml (which is good in this case)
-- while getxmltype can not.
select dbms_xmlgen.getxml(q'{
SELECT TEXT as LONGCOL
FROM SYS.DBA_VIEWS
WHERE VIEW_NAME = '}' || input.VIEW_NAME || q'{'
}') as text_xml
from input
)
or create our own DBA_VIEWS version.
create or replace view APP_SCHEMA.DBA_VIEWS
as
select
OWNER, VIEW_NAME, TEXT_LENGTH,
case
when (TEXT_VC is not null and TEXT_LENGTH <= 4000)
then to_clob(TEXT_VC)
when TEXT is NULL
then NULL
else (
SELECT
substr(
text_xml,
instr(text_xml, '<LONGCOL>') + length('<LONGCOL>'),
--instr(text_xml, '</LONGCOL>', -1) - (instr(text_xml, '<LONGCOL>') + length('<LONGCOL>'))
TEXT_LENGTH
) as TEXT
from
(
-- getxml can return malformed xml (which is good in this case)
-- while getxmltype can not.
select dbms_xmlgen.getxml(q'{
SELECT TEXT as LONGCOL
FROM SYS.DBA_VIEWS
WHERE OWNER = '}' || OWNER || q'{'
and VIEW_NAME = '}' || VIEW_NAME || q'{'
}') as text_xml
from dual
)
)
end as TEXT,
TEXT_VC, TYPE_TEXT_LENGTH, TYPE_TEXT, OID_TEXT_LENGTH, OID_TEXT, VIEW_TYPE_OWNER, VIEW_TYPE, SUPERVIEW_NAME, EDITIONING_VIEW, READ_ONLY, CONTAINER_DATA, BEQUEATH, ORIGIN_CON_ID, DEFAULT_COLLATION, CONTAINERS_DEFAULT, CONTAINER_MAP, EXTENDED_DATA_LINK, EXTENDED_DATA_LINK_MAP, HAS_SENSITIVE_COLUMN
from sys.dba_views
;

SQLRPGLE & JSON_OBJECT CTE Statements -101 Error

This program compiles correctly, we are on V7R3 - but when running it receives an SQLCOD of -101 and an SQLSTATE code is 54011 which states: Too many columns were specified for a table, view, or table function. This is a very small JSON that is being created so I do not think that is the issue.
The RPGLE code:
dcl-s OutFile sqltype(dbclob_file);
xfil_tofile = '/ServiceID-REFCODJ.json';
Clear OutFile;
OutFile_Name = %TrimR(XFil_ToFile);
OutFile_NL = %Len(%TrimR(OutFile_Name));
OutFile_FO = IFSFileCreate;
OutFile_FO = IFSFileOverWrite;
exec sql
With elm (erpRef) as (select json_object
('ServiceID' VALUE trim(s.ServiceID),
'ERPReferenceID' VALUE trim(i.RefCod) )
FROM PADIMH I
INNER JOIN PADGUIDS G ON G.REFCOD = I.REFCOD
INNER JOIN PADSERV S ON S.GUID = G.GUID
WHERE G.XMLTYPE = 'Service')
, arr (arrDta) as (values json_array (
select erpRef from elm format json))
, erpReferences (refs) as ( select json_object ('erpReferences' :
arrDta Format json) from arr)
, headerData (hdrData) as (select json_object(
'InstanceName' : trim(Cntry) )
from padxmlhdr
where cntry = 'US')
VALUES (
select json_object('header' : hdrData format json,
'erpReferenceData' value refs format json)
from headerData, erpReferences )
INTO :OutFile;
Any help with this would be very much appreciated, this is our first attempt at creating JSON for sending and have not experienced this issue before.
Thanks,
John
I am sorry for the delay in getting back to this issue. It has been corrected, the issue was with the "values" statement.
This is the correct code needed to make it work correctly:
Select json_object('header' : hdrData format json,
'erpReferenceData' value refs format json)
INTO :OutFile
From headerData, erpReferences )

Is MERGE supported in Greenplum Database 4.3.5.1 build 1

I am trying to create a merge statement for Greenplum DB and I am getting an syntax error. So I am wondering if the MERGE is even supported the way I am writing it.
I have two approaches
Approach 1-
MERGE into public.table20 pritab
USING
(
select stgout.key1, stgout.key2, stgout.col1
from public.table20_stage stgout
where stgout.sequence_id < 1000
) as stgtab
ON (pritab.key1 = stgtab.key1
and pritab.key2 = stgtab.key2)
WHEN MATCHED THEN
UPDATE SET pritab.key1 = stgtab.key1
,pritab.key2 = stgtab.key2
,pritab.col1 = stgtab.col1
WHEN NOT MATCHED THEN
INSERT (key1, key2, col1)
values (stgtab.key1, stgtab.key2, stgtab.col1);
Approach 2:
public.table20 pritab
SET pritab.key1 = stgtab.key1
,pritab.key2 = stgtab.key2
,pritab.col1 = stgtab.col1
from
(
select stgout.key1, stgout.key2, stgout.col1
from public.table20_stage stgout
where stgout.sequence_id < 1000
) as stgtab
ON (pritab.key1 = stgtab.key1
and pritab.key2 = stgtab.key2)
returning (stgtab.key1, stgtab.key2, stgtab.col1);
Is there any other way or something is wrong with my syntax itself?
Merge is not supported in Greenplum but I wrote a blog post on how to achieve the results of a merge statement in Greenplum.
http://www.pivotalguru.com/?p=104

Query returning -> ORA-19011: Character string buffer too small

i'm running this query below, and oracle returning the following message: Query returning -> ORA-19011: Character string buffer too small
When i uncomment the last line, it works. I think thats why this return few results. how to solve this?
select substr(xmlagg(xmlelement (e, str||',')).extract ('//text()'),1,(Length(Trim(xmlagg (xmlelement (e, str||',')).extract ('//text()')))-2)) motivos
FROM (
select to_char(lo_valor) str
from editor_layout el,
editor_versao_documento ev,
editor_documento ed,
editor_layout_campo elc,
editor_campo ec,
editor_registro er,
editor_registro_campo erc,
pw_editor_clinico pec,
pw_documento_clinico pdc
where pec.cd_editor_registro = er.cd_registro
and pdc.cd_documento_clinico = pec.cd_documento_clinico
and ed.cd_documento = ev.cd_documento
and el.cd_versao_documento = ev.cd_versao_documento
and el.cd_layout = elc.cd_layout
and elc.cd_campo = ec.cd_campo
and elc.cd_campo = erc.cd_campo
and er.cd_registro = erc.cd_registro
and er.cd_layout = el.cd_layout
and ec.ds_identificador = 'nut_orientacoes_entregues_1'
AND To_Char(lo_valor) IS NOT null
--and Trunc(pdc.dh_documento) BETWEEN Trunc(SYSDATE-5) AND Trunc(SYSDATE)
)
The contents of the xmlagg(xmlelement ...) call returns a clob, and you are trying to stuff it into a varchar2 since you call substr for example. That will fail if the clob is too large.
The reason it will fail when you uncomment the last line is that outside that range, there are rows having the contents that is too long.

1 result set from 3 queries?

I'm at my wits end attempting to make this happen. Currently I have 3 separate queries. For automation purposes I need to get the results of these three queries in one output, I cannot seem to join them properly to get the expected results.
QUERY 1:
SELECT OH.EXTN_HOST_ORDER_REF,
OL.EXTN_HOST_ORDER_LINE_REF,
OL.ORIGINAL_ORDERED_QTY,
OL.EXTN_TENDER_QUANTITY,
OL.EXTN_CUM_PICK_QTY,
OL.SHIPPED_QUANTITY,
OL.EXTN_REFUND_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OH.DOCUMENT_TYPE = '0001'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx'
ORDER BY PL.EXTN_HOST_ORDER_LINE_REF ASC;
QUERY 2:
SELECT RS.STATUS_QUANTITY AS RETURNED_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL,
YFS_ORDER_RELEASE_STATUS RS
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OL.ORDER_LINE_KEY = RS.ORDER_LINE_KEY
AND RS.STATUS = '3700.02'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx';
QUERY 3
SELECT RS.STATUS_QUANTITY AS CANCELLED_QTY
FROM YFS_ORDER_HEADER OH,
YFS_ORDER_LINE OL,
YFS_ORDER_RELEASE_STATUS RS
WHERE OH.ORDER_HEADER_KEY = OL.ORDER_HEADER_KEY
AND OL.ORDER_LINE_KEY = RS.ORDER_LINE_KEY
AND RS.STATUS = '9000'
AND OH.EXTN_HOST_ORDER_REF = 'xxxxxxxxxxx';
The query should show NULL values where no data exists from query 2 & 3.
Thanks in advance for your help and advice!
If you are allowed to show both returned and cancelled quantities, the following simple edit should work. Hope this helps.
SELECT oh.extn_host_order_ref,
ol.extn_host_order_line_ref,
ol.original_ordered_qty,
ol.extn_tender_quantity,
ol.extn_cum_pick_qty,
ol.shipped_quantity,
ol.extn_refund_qty,
DECODE (rs.status, '3700.02', rs.status_quantity) AS returned_qty,
DECODE (rs.status, '9000', rs.status_quantity) AS cancelled_qty
FROM yfs_order_header oh
INNER JOIN yfs_order_line ol
ON oh.order_header_key = ol.order_header_key
LEFT OUTER JOIN yfs_order_release_status rs
ON ol.order_line_key = rs.order_line_key
WHERE oh.document_type = '0001' AND oh.extn_host_order_ref = 'xxxxxxxxxxx'
ORDER BY pl.extn_host_order_line_ref ASC;

Resources