I want to use dynamic sql in Netezza for this example. But I can't.
In general, I want to know if I can use dynamic instances for parts of the code that do not require "execute immediate". For instance the condition of an If else statement. I basically dont know how to use dynamic sql when I have several statements in a row. Any comments are appreciated.
CREATE OR REPLACE PROCEDURE "SP_Count_Ndays_between_date1_date2_where" (DATE, DATE, varchar(400), varchar(400))
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
START_DATE ALIAS FOR $1;
END_DATE ALIAS FOR $2;
whichweekdays ALIAS FOR $3;
whichdaysofmonth ALIAS FOR $4;
CURR_DATE DATE;
DAY_COUNT INT;
sql varchar(40000);
BEGIN
DAY_COUNT = 0;
CURR_DATE = START_DATE;
WHILE CURR_DATE <= END_DATE
LOOP
IF '(extract(dow from CURR_DATE) IN'|| whichweekdays||' and extract(day from CURR_DATE) IN'|| whichdaysofmonth||')'
THEN DAY_COUNT = DAY_COUNT + 1;
End if ;
CURR_DATE = CURR_DATE + 1;
END LOOP;
RETURN DAY_COUNT;
END;
END_PROC;
You can use a mixture of static and dynamic SQL to tackle this problem.
Keep your outer loop, and then reate a dynamic SQL string on each step of your outer loop. Then use that result in an inner FOR IN EXECUTE LOOP block.
Mine the boolean result from that, do your non-dynamic IF-THEN, and then keep on looping.
CREATE OR REPLACE PROCEDURE SP_Count_Ndays_between_date1_date2_where (DATE, DATE, varchar(400), varchar(400))
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
START_DATE ALIAS FOR $1;
END_DATE ALIAS FOR $2;
whichweekdays ALIAS FOR $3;
whichdaysofmonth ALIAS FOR $4;
CURR_DATE DATE;
DAY_COUNT INT;
sql varchar(40000);
vResult record;
BEGIN
DAY_COUNT = 0;
CURR_DATE = START_DATE;
WHILE CURR_DATE <= END_DATE
LOOP
sql := 'SELECT (
extract(dow from ''' || CURR_DATE|| '''::DATE) IN ('|| whichweekdays||') and extract(day from ''' || CURR_DATE || '''::DATE) IN ('|| whichdaysofmonth|| ')
) bool_test' ;
RAISE NOTICE '%', sql;
for vResult in execute sql LOOP
RAISE NOTICE 'Date: %, Test Result %', CURR_DATE, vResult.bool_test;
IF vResult.bool_test then
DAY_COUNT = DAY_COUNT +1;
END IF;
END LOOP;
CURR_DATE = CURR_DATE + 1;
END LOOP;
RETURN DAY_COUNT;
END;
END_PROC;
Results, with my overly verbose debug statements, here:
TESTDB.ADMIN(ADMIN)=> exec SP_Count_Ndays_between_date1_date2_where (CURRENT_DATE, CURRENT_DATE + '4 days'::interval, '4,5,6', '7,8,9,10,11');
NOTICE: SELECT (
extract(dow from '2015-08-07'::DATE) IN (4,5,6) and extract(day from '2015-08-07'::DATE) IN (7,8,9,10,11)
) bool_test
NOTICE: Date: 2015-08-07, Test Result t
NOTICE: SELECT (
extract(dow from '2015-08-08'::DATE) IN (4,5,6) and extract(day from '2015-08-08'::DATE) IN (7,8,9,10,11)
) bool_test
NOTICE: Date: 2015-08-08, Test Result f
NOTICE: SELECT (
extract(dow from '2015-08-09'::DATE) IN (4,5,6) and extract(day from '2015-08-09'::DATE) IN (7,8,9,10,11)
) bool_test
NOTICE: Date: 2015-08-09, Test Result f
NOTICE: SELECT (
extract(dow from '2015-08-10'::DATE) IN (4,5,6) and extract(day from '2015-08-10'::DATE) IN (7,8,9,10,11)
) bool_test
NOTICE: Date: 2015-08-10, Test Result f
NOTICE: SELECT (
extract(dow from '2015-08-11'::DATE) IN (4,5,6) and extract(day from '2015-08-11'::DATE) IN (7,8,9,10,11)
) bool_test
NOTICE: Date: 2015-08-11, Test Result f
SP_COUNT_NDAYS_BETWEEN_DATE1_DATE2_WHERE
------------------------------------------
1
(1 row)
Related
I receive information to my SQL Server table by uploading an Excel file on the web.
I have to create a stored procedure where I have to select a line (part of my table), the name of the month and the year that I want to get that information. So there are three parameters.
I show an example of the query I'm doing.
ALTER PROCEDURE SP_NIVELES(
#NIVEL VARCHAR(15),
#MES VARCHAR(12),
#AÑO INT
)
AS
BEGIN
IF #NIVEL = 'LINEA MC'
BEGIN
SELECT LINEAMC, SUM(MONTODEBITO) AS DEBITO, SUM(MONTOCREDITO) AS CREDITO, SUM(MONTODEBITO) - SUM(MONTOCREDITO) AS TOTAL
FROM PRUEBAOPEX p
WHERE MES = #MES
AND AÑO = #AÑO
GROUP BY LINEAMC
END
ELSE
RAISERROR('Linea Incorrecta', 16, 1)
END
My problem is that the "MES" column is of type varchar and my "AÑO" column is of type int.
I need to get the information from the previous month (in addition to the month I select as a parameter), is there a way to get the previous month when the "MONTH" field is of type varchar? Or is there a way to include the date data type for this query (would be more efficient I think)? If it existed, what would it be like?
I think you're going to have to CONVERT to a real date and do your math on that. Hopefully your server localized to your language, try this and see if it recognizes you rmonth names
ALTER PROCEDURE SP_NIVELES(
#NIVEL VARCHAR(15),
#MES VARCHAR(12),
#AÑO INT
)
AS
BEGIN
IF #NIVEL = 'LINEA MC'
BEGIN
with cteDates as (
SELECT DATEADD(month, 1, CONVERT(DATE, CONCAT(#MES, ' 1, ', CONVERT(char(5), #Ano)))) as TooLate
, DATEADD(month, -1, CONVERT(DATE, CONCAT(#MES, ' 1, ', CONVERT(char(5), #Ano)))) as Earliest
)
SELECT LINEAMC, SUM(MONTODEBITO) AS DEBITO, SUM(MONTOCREDITO) AS CREDITO, SUM(MONTODEBITO) - SUM(MONTOCREDITO) AS TOTAL
FROM PRUEBAOPEX as p CROSS JOIN cteDates as D
WHERE CONVERT(DATE, CONCAT(#MES, ' 1, ', CONVERT(char(5), #Ano))) < TooLate
AND CONVERT(DATE, CONCAT(#MES, ' 1, ', CONVERT(char(5), #Ano))) >= Earliest
GROUP BY LINEAMC
END
ELSE
RAISERROR('Linea Incorrecta', 16, 1)
END
I presume #MES will contain the name of the month in Spanish. You could try and get the month number out of its name but that can be problematic depending on the localization of your database. In your case I would do something like the following:
ALTER PROCEDURE SP_NIVELES(
#NIVEL VARCHAR(15),
#MES VARCHAR(12),
#AÑO INT
)
AS
BEGIN
DECLARE #MesAnterior NVARCHAR(12), #AñoMesAnterior INT;
SET #MesAnterior = CASE #MES
WHEN 'Enero' THEN 'Diciembre'
WHEN 'Febrero' THEN 'Enero'
WHEN 'Marzo' THEN 'Febrero'
WHEN 'Abril' THEN 'Marzo'
WHEN 'Mayo' THEN 'Abril'
WHEN 'Junio' THEN 'Mayo'
WHEN 'Julio' THEN 'Junio'
WHEN 'Agosto' THEN 'Julio'
WHEN 'Septiembre' THEN 'Agosto'
WHEN 'Octubre' THEN 'Septiembre'
WHEN 'Noviembre' THEN 'Octubre'
WHEN 'Diciembre' THEN 'Noviembre'
END;
SET #AñoMesAnterior = CASE #MES WHEN 'Enero' THEN #AÑO - 1 ELSE #AÑO END;
IF #NIVEL = 'LINEA MC'
BEGIN
SELECT LINEAMC, SUM(MONTODEBITO) AS DEBITO, SUM(MONTOCREDITO) AS CREDITO, SUM(MONTODEBITO) - SUM(MONTOCREDITO) AS TOTAL
FROM PRUEBAOPEX p
WHERE (MES = #MES AND AÑO = #AÑO) OR (MES = #MesAnterior AND AÑO = #AñoMesAnterior)
GROUP BY LINEAMC
END
ELSE
RAISERROR('Linea Incorrecta', 16, 1)
END
Of course, this would work if the names of the months are "known" and uniform across your table.
Hope it helps
How to calculate a GS1 check digit for GTIN and SSCC codes in SQL Server.
This User-Defined Function will calculate check digits for all of the mentioned GTIN and SSCC formats on the GS1 website. The function will return the code that includes the check digit as a last character.
CREATE FUNCTION [GtinCheckDigit] (#Input VARCHAR(17))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN WITH [ReverseInput](S) AS (
SELECT REVERSE(#Input)
), [CharCount](N) AS (
SELECT n from (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17)) a(n)
), [CharPos](N,S) AS (
SELECT TOP (LEN(#Input)) [CharCount].N,SUBSTRING([ReverseInput].S,[CharCount].N,1)
FROM [CharCount],[ReverseInput]
), [Multiplier](N) AS (
SELECT (S*CASE WHEN (N%2) = 0 THEN 1 ELSE 3 END)
FROM [CharPos]
), [Checksum](N) AS (
SELECT CASE WHEN (SUM(N)%10) > 0 THEN (10-(SUM(N)%10)) ELSE 0 END
FROM [Multiplier]
)
SELECT #Input + CAST(N as VARCHAR) as [Output] from [Checksum];
If you only need to retreive the calculated check digit you can change the last line of the function to something like this:
SELECT N from [Checksum];
This function will only work on SQL-Server 2008 or higher because of the REVERSE function that is being used to reverse the input.
In case you are looking for PostgreSQL GS1 check digit calculation under this thread:
CREATE OR REPLACE FUNCTION gs1_check_digit(code TEXT)
RETURNS TEXT
AS $$
#variable_conflict error
DECLARE
digit SMALLINT;
digit_3x BOOL DEFAULT TRUE;
digit_sum SMALLINT DEFAULT 0;
digit_index SMALLINT DEFAULT 1;
digit_count SMALLINT;
BEGIN
IF code IS NULL THEN
RETURN '';
END IF;
digit_count := LENGTH(code);
IF digit_count = 0 THEN
RETURN '';
END IF;
code := REVERSE(code);
LOOP
digit := SUBSTRING(code, digit_index, 1)::SMALLINT;
IF digit_3x THEN
digit := digit*3;
END IF;
digit_sum := digit_sum + digit;
digit_index := digit_index + 1;
IF digit_index > digit_count THEN
EXIT;
END IF;
digit_3x = (NOT digit_3x);
END LOOP;
RETURN CASE WHEN digit_sum%10=0 THEN digit_sum ELSE (digit_sum/10+1)*10 END - digit_sum;
END;
$$ LANGUAGE PLPGSQL;
CREATE OR ALTER FUNCTION dbo.udfGetUPCCheckDigit
(
#Code AS VARCHAR(50)
)
RETURNS int
AS
BEGIN
Declare #ret int;
WITH Totals (n) AS
(
SELECT TOP (LEN(#Code))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(n)
)
SELECT #ret = (10 -
SUM(CASE n%2
WHEN 1 THEN 3
ELSE 1 END * SUBSTRING(#Code, n, 1))
% 10
) % 10
FROM Totals;
Return #ret
END;
I want this procedure change the table name when I execute it.
The table name that I want to change is Recargas_#mes
There is some way to do that?
#MES DATETIME
AS
BEGIN
SELECT CUENTA, SUM(COSTO_REC) COSTO_REC
INTO E09040_DEV.BI_PRO_COSTO_RECARGAS
FROM (
SELECT a.*,(CASE
WHEN COD_AJUSTE IN ('ELEC_TEXT','TFREPPVV_C') THEN (A.VALOR)*(R.COSTO) ELSE 0 END)
FROM Recargas_#MES AS A, BI_PRO_LISTA_COSTOS_RECARGAS AS R
WHERE R.ANO_MES = #MES
) D
GROUP BY CUENTA
END
Sample code:
-- Declare variables
DECLARE #MES DATETIME;
DECLARE #TSQL NVARCHAR(MAX);
-- Set the variable to valid statement
SET #TSQL = N'
SELECT CUENTA, SUM(COSTO_REC) AS COSTO_REC
INTO E09040_DEV.BI_PRO_COSTO_RECARGAS
FROM (
SELECT A.*,
(CASE
WHEN COD_AJUSTE IN (''ELEC_TEXT'',''TFREPPVV_C'') THEN
(A.VALOR)*(R.COSTO)
ELSE 0
END)
FROM
Recargas_' + REPLACE(CONVERT(CHAR(10), #MES, 101), '/', '') + ' AS A,
BI_PRO_LISTA_COSTOS_RECARGAS AS R
WHERE R.ANO_MES = ' + CONVERT(CHAR(10), #MES, 101) + '
) D
GROUP BY CUENTA'
-- Execute the statement
EXECUTE (#SQL)
Some things to note:
1 - I assume the table name has some type of extension that is a date? I used MM/DD/YYYY and removed the slashes as a format for the suffix.
2 - The WHERE clause will only work if you are not using the time part of the variable.
For instance, 03/15/2016 00:00:00 would be date without time entry. If not, you will have to use >= and < to grab all hours for a particular day.
3 - You are creating a table on the fly with this code. On the second execution, you will get a error unless you drop the table.
4 - You are not using the ON clause when joining table A to table R. To be ANSI compliant, move the WHERE clause to a ON clause.
5 - The actual calculation created by the CASE statement is not give a column name.
Issues 3 to 5 have to be solved on your end since I do not have the detailed business requirements.
Have Fun.
It should work using dynamic SQL to allow putting a dynamic table name:
DECLARE #SQL NVARCHAR(MAX) = N'
SELECT CUENTA, SUM(COSTO_REC) COSTO_REC
INTO E09040_DEV.BI_PRO_COSTO_RECARGAS
FROM (
SELECT a.*,(CASE
WHEN COD_AJUSTE IN (''ELEC_TEXT'',''TFREPPVV_C'') THEN (A.VALOR)*(R.COSTO) ELSE 0 END)
FROM Recargas_' + #MES + ' AS A, BI_PRO_LISTA_COSTOS_RECARGAS AS R
WHERE R.ANO_MES = ' + CAST(#MES AS VARCHAR(32)) + '
) D
GROUP BY CUENTA'
EXECUTE (#SQL)
I have a table and it has a 3 columns. The first column is the data that contains value(numeric) and unit(percentage and etc..), the second column is numeric column, the third is Unit column. What I want to do is split the numeric and the unit from the first column then put those split-ted data to its designated column.
Here is my table:
I tried this function:SO link here..., it really does splitting alpha and numeric but then I'm new in using SQL Function, my problem there is the parameter must be in string STRING, so what I did is change it to Sub Query but it gives me error.
Sample COde:
SQL FUNCTION:
create function [dbo].[GetNumbersFromText](#String varchar(2000))
returns table as return
(
with C as
(
select cast(substring(S.Value, S1.Pos, S2.L) as int) as Number,
stuff(s.Value, 1, S1.Pos + S2.L, '') as Value
from (select #String+' ') as S(Value)
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
union all
select cast(substring(S.Value, S1.Pos, S2.L) as int),
stuff(S.Value, 1, S1.Pos + S2.L, '')
from C as S
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
where patindex('%[0-9]%', S.Value) > 0
)
select Number
from C
)
SELECT STATEMENT with SUB Query:
declare #S varchar(max)
select number from GetNumbersFromText(Select SomeColm From Table_Name) option (maxrecursion 0)
BTW, im using sql server 2005.
Thanks!
If the numeric part is always at the beginning, then you can use this:
PATINDEX('%[0-9][^0-9]%', ConcUnit)
to get the index of the last digit.
Thus, this:
DECLARE #str VARCHAR(MAX) = '4000 ug/ML'
SELECT LEFT(#str, PATINDEX('%[0-9][^0-9]%', #str )) AS Number,
LTRIM(RIGHT(#str, LEN(#str) - PATINDEX('%[0-9][^0-9]%', #str ))) As Unit
gives you:
Number Unit
-------------
4000 ug/ML
EDIT:
If numeric data include double values as well, then you can use this:
SELECT LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))
to get the index of the last digit.
Thus, this:
SELECT LEFT(#str, LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str)))
gives you the numeric part.
And this:
SELECT LEFT(#str, LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))) AS Numeric,
CASE
WHEN CHARINDEX ('%', #str) <> 0 THEN LTRIM(RIGHT(#str, LEN(#str) - CHARINDEX ('%', #str)))
ELSE LTRIM(RIGHT(#str, PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))))
END AS Unit
gives you both numberic and unit part.
Here are some tests that I made with the data you have posted:
Input:
DECLARE #str VARCHAR(MAX) = '50 000ug/ML'
Output:
Numeric Unit
------------
50 000 ug/ML
Input:
DECLARE #str VARCHAR(MAX) = '99.5%'
Output:
Numeric Unit
------------
99.5
Input:
DECLARE #str VARCHAR(MAX) = '4000 . 35 % ug/ML'
Output:
Numeric Unit
------------------
4000 . 35 ug/ML
Here is my answer. Check output in SQLFiddle for the same.
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml')
SELECT subsrtunit,LEFT(subsrtnumeric, PATINDEX('%[^0-9]%', subsrtnumeric+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9]%', string),
posofnumber = PATINDEX('%[0-9]%', string)
FROM temp
) d
) t
Updated Version to handle 99.5 ug\ml
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml'),
('99.5 ug\ml')
SELECT subsrtunit,LEFT(subsrtnumeric, PATINDEX('%[^0-9.]%', subsrtnumeric+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9.]%', string),
posofnumber = PATINDEX('%[0-9.]%', string)
FROM temp
) d
) t
Updated Version: To handle 1 000 ug\ml,20 000ug\ml
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml'),
('99.5 ug\ml'),
('1 000 ug\ml'),
('20 000ug\ml')
SELECT substring(replace(subsrtunit,' ',''),PATINDEX('%[0-9.]%', replace(subsrtunit,' ',''))+1,len(subsrtunit)),
LEFT(replace(subsrtnumeric,' ',''), PATINDEX('%[^0-9.]%', replace(subsrtnumeric,' ','')+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9.]%', replace(string,' ','')),
posofnumber = PATINDEX('%[0-9.]%', replace(string,' ',''))
FROM temp
) d
) t
Check out SQLFiddle for the same.
Would something like this work? Based on the shown data it looks like it would.
Apply it to your data set as a select and if you like the results then you can make an update from it.
WITH cte as (SELECT 'ug/mL' ConcUnit, 500 as [Numeric], '' as Unit
UNION ALL SELECT '2000 ug/mL', NULL, '')
SELECT
[ConcUnit] as [ConcUnit],
[Numeric] as [Original Numeric],
[Unit] as [Original Unit],
CASE WHEN ConcUnit LIKE '% %' THEN
SUBSTRING(ConcUnit, 1, CHARINDEX(' ', ConcUnit) - 1)
ELSE [Numeric] END as [New Numeric],
CASE WHEN ConcUnit LIKE '% %'
THEN SUBSTRING(ConcUnit, CHARINDEX(' ', ConcUnit) + 1, LEN(ConcUnit))
ELSE ConcUnit END as [New Unit]
FROM cte
change #concunit & #unitx Respectively
DECLARE #concunit varchar(10)='45.5%'
DECLARE #unitx varchar(10)='%'
BEGIN
SELECT RTRIM(SUBSTRING( #concunit , 1 , CHARINDEX( #unitx , #concunit
) - 1
)) AS Number,
RTRIM(SUBSTRING( #concunit , CHARINDEX( #unitx , #concunit
) , LEN( #concunit
) - (CHARINDEX( #unitx , #concunit
) - 1)
)) AS Unit
end
I had the same dilemma, but in my case the alpha's were in front of the numerics.
So using the logic that #Giorgos Betsos added to his answer, I just reversed it.
I.e., when your input is :
abc123
You can split it like this:
declare #input varchar(30) = 'abc123'
select
replace(#input,reverse(LEFT(reverse(#input), PATINDEX('%[0-9][^0-9]%', reverse(#input) ))),'') Alpha
, reverse(LEFT(reverse(#input), PATINDEX('%[0-9][^0-9]%', reverse(#input) ))) Numeric
Results :
I am new to Oracle. Come from an SQL / Sybase background and struggling to create a procedure that simply should output a set of fields from a table.
I am looking to create a Stored Procedure in Oracle that is equivalent on SQL/Sybase as follows;
CREATE PROCEDURE ListTransactions #StartDate datetime, #EndDate datetime AS
DECLARE #ReportDate datetime
SET #ReportDate = CONVERT(datetime,CONVERT(VARCHAR,GETDATE(), 103), 103)
SELECT
#ReportDate,
trn.TransactionDate,
cp.CounterPartyName,
cu.Currency_Name,
trn.Amount,
trn.PostedBy,
trn.Comments
FROM
Transactions trn
LEFT JOIN CounterParties cp ON trn.CounterParty_Id = cp.CounterParty_Id
LEFT JOIN Currency cu ON trn.Currency_Id = cu.Currency_Id
WHERE
trn.TransactionDate Between #StartDate AND #EndDate
The following should do something like what you want:
CREATE OR REPLACE FUNCTION LIST_TRANSACTIONS(pStartDate IN DATE,
pEndDate IN DATE)
RETURN SYS_REFCURSOR IS
DECLARE
csr SYS_REFCURSOR;
BEGIN
OPEN csr FOR
SELECT TRUNC(SYSDATE),
trn.TransactionDate,
cp.CounterPartyName,
cu.Currency_Name,
trn.Amount,
trn.PostedBy,
trn.Comments
FROM Transactions trn
LEFT OUTER JOIN CounterParties cp
ON trn.CounterParty_Id = cp.CounterParty_Id
LEFT OUTER JOIN Currency cu
ON trn.Currency_Id = cu.Currency_Id
WHERE trn.TransactionDate BETWEEN pStartDate
AND pEndDate;
RETURN csr;
END LIST_TRANSACTIONS;
I don't understand what you meant by "output a set of fields from a table". This function will return a cursor that the caller can subsequently iterate. For example, if you wanted to dump the results of the cursor to DBMS_OUTPUT you could do something like the following anonymous block:
DECLARE
c SYS_REFCURSOR;
dtDate DATE;
dtTransaction_date DATE;
strCounterPartyName VARCHAR2(100);
strCurrency_Name VARCHAR2(100);
nAmount NUMBER;
strPostedBy VARCHAR2(100);
strComments VARCHAR2(2000);
BEGIN
c := LIST_TRANSACTIONS(pStartDate => SYSDATE - INTERVAL '1' MONTH,
pEndDate => SYSDATE);
LOOP
FETCH c
INTO dtDate,
dtTransaction_date,
strCounterPartyName,
strCurrency_Name,
nAmount,
strPostedBy,
strComments;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Date=' || dtDate ||
'Transaction date=' || dtTransaction_date ||
'Counter-party namme=' || strCounterPartyName ||
'Currency name=' || strCurrency_Name ||
'Amount=' || nAmount ||
'Posted by=' || strPostedBy ||
'Comments=' || strComments);
END LOOP;
CLOSE c;
END;
Not tested on animals - you'll be first!
Share and enjoy.