my procedure is like below;
CREATE OR REPLACE PROCEDURE updateWEEK_SALES_REPORTS
( p_start IN WEEK_SALES_REPORT.StartDate%TYPE,
p_end IN weekly_sales_report.EndDate%TYPE)
IS
BEGIN
UPDATE WEEK_SALES_REPORT SET ComAmount = SaleAmount*ComRate WHERE (StartDate-EndDate) = (p_start-p_end);
SELECT concat('The commission amount for report ',ReportID,' has been updated to ',ComAmount,' dollars,
which is',ComRate,'% of the total sale amount of ',SaleAmount,' dollars.')
COMMIT;
END;
/
but show errors is
7/3 PL/SQL: SQL Statement ignored
7/10 PL/SQL: ORA-00909: invalid number of arguments
I'm pretty sure you're trying to print your message to the console. For that, you want dbms_output.
CREATE OR REPLACE PROCEDURE updateWEEK_SALES_REPORTS
( p_start IN date,
p_end IN date)
IS
BEGIN
UPDATE WEEK_SALES_REPORT SET ComAmount = SaleAmount*ComRate WHERE (StartDate-EndDate) = (p_start-p_end);
dbms_output.put_line('The commission amount for report ' || ReportID || ' has been updated to ' || ComAmount || ' dollars,
which is' || ComRate || '% of the total sale amount of ' || SaleAmount || ' dollars.');
COMMIT;
END;
Yes, #Jacob H is right, CONCAT takes only 2 parameters. Use || instead, much uglier than your version, though:
SELECT 'The commission amount for report ' || ReportID ||
' has been updated to ' || ComAmount || ' dollars, which is' ||
ComRate || '% of the total sale amount of ' || SaleAmount ||
' dollars.' ...
Furthermore, you need to SELECT it INTO some variable like, f.i.
SELECT ... INTO myvar FROM DUAL;
Related
The procedure takes two dates and find the reports that issued during this duration, and update total salary, and print them.
CREATE OR REPLACE PROCEDURE Salary_Update(p_Date1 DATE, p_Date2 DATE) AS
CURSOR MYCR IS
SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
FROM WEEKLY_REPORT
WHERE ReportDate BETWEEN TO_DATE(p_Date1, 'DD-MM-YYYY') AND TO_DATE(p_Date2, 'DD-MM-YYYY');
BEGIN
FOR MYPOINTER IN MYCR LOOP
UPDATE WEEKLY_REPORT SET TotalSalary = ((TotalSale/100)*Rate);
DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || ' updated to ' || MYPOINTER.TotalSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
WHERE ReportID = MYPOINTER.ReportID;
END LOOP;
END Salary_Update;
/
the execution
BEGIN Salary_Update('02-04-2020','05-04-2020');
END;
BEGIN
Salary_Update(to_date('02-04-2020','dd-mm-yyyy'), to_date('05-04-2020','dd-mm-yyyy'));
END;
both don't work.
There are a number of syntax and logic errors. You haven't specified exactly what you want the code to do or provided a reproducible test case but my guess is that you want something like
CREATE OR REPLACE PROCEDURE Salary_Update(
p_Date1 DATE,
p_Date2 DATE)
AS
CURSOR MYCR IS
SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
FROM WEEKLY_REPORT
WHERE ReportDate BETWEEN p_date1 AND p_date2;
BEGIN
FOR MYPOINTER IN MYCR
LOOP
UPDATE WEEKLY_REPORT
SET TotalSalary = ((TotalSale/100)*Rate)
WHERE ReportID = MYPOINTER.ReportID;
DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || ' updated to ' || MYPOINTER.TotalSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
END LOOP;
END Salary_Update;
/
The string you're outputting doesn't seem to make sense-- MYPOINTER.TotalSalary is the value from the cursor which will be the value from before the update. If it is important that you print out the value you updated TotalSalary to, you'd probably want something like
CREATE OR REPLACE PROCEDURE Salary_Update(
p_Date1 DATE,
p_Date2 DATE)
AS
CURSOR MYCR IS
SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
FROM WEEKLY_REPORT
WHERE ReportDate BETWEEN p_date1 AND p_date2;
l_newSalary weekly_report.totalSalary%type;
BEGIN
FOR MYPOINTER IN MYCR
LOOP
l_newSalary := (mypointer.TotalSale/100) * mypointer.rate;
UPDATE WEEKLY_REPORT
SET TotalSalary = l_newSalary
WHERE ReportID = MYPOINTER.ReportID;
DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || ' updated to ' || l_newSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
END LOOP;
END Salary_Update;
/
If the error that you're getting is an ORA-00942 error that weekly_report doesn't exist, then there is no such table in the current schema. Assuming that the query works when run interactively, potentially the table exists in a different schema, there is a local synonym in the current schema for that table, and the owner of the procedure only has access to the table granted via a role. In that case, you'd need your DBA to grant access to the table directly to the owner of the procedure.
I have already asked almost the same question before:
Finding non-numeric values in varchar column
And I received some great answer's and idea's to make not only fix the issue in my query but also make it much more efficient.
Old Query:
Select * From Table_Name
Where
(NOT REGEXP_LIKE(COLUMN_NAME, '^-?[0-9.]+$')
OR
LENGTH(Function_To_Fetch_Left_Component(COLUMN_NAME)) > (Precision-Scale)
OR
LENGTH(Column_Name) - LENGTH(REPLACE(Column_Name,'.','')) > 1)
New Query:
Select * From Table_Name
WHERE (Translate(column_name,'x0123456789-.','x') is not null
OR column_name = '.'
OR column_name = '-'
OR column_name = '-.'
OR Instr(column_name,'-') > 1
OR column_name like '%-%-%'
OR column_name like '%.%.%'
OR Instr(column_name||'.','.')-1 > (precision-scale) ) ;
Known limitations which are okay:
1.) Doesn't handle scientific notation. Its by design as I want to reject those.
2.) Doesn't check total precision (decimal component) however as while inserting oracle itself round's it off I am fine with it.
3.) Doesn't check for leading zero's.
Please help to see if the above query cover's everything and I haven't missing anything.
Another great solution by one Stackoverflow member however increased execution time by 2.5 times:
Function:
CREATE OR REPLACE function temp_is_number(p_test_value varchar2,
p_scale NUMBER,
p_precision NUMBER) return varchar2 is
l_result varchar2(1);
begin
execute immediate 'DECLARE l_number NUMBER; ' ||
'l_test_number NUMBER(' || p_precision || ',' || p_scale || '); ' ||
'BEGIN ' ||
' l_number := cast(:b1 as number); ' ||
' l_test_number := cast(:b1 as number); ' ||
' IF (l_number = l_test_number) THEN ' ||
' :b2 := ''Y''; ' ||
' ELSE ' ||
' :b2 := ''N''; ' ||
' END IF; ' ||
'EXCEPTION ' ||
' WHEN OTHERS THEN ' ||
' :b2 := ''N''; ' ||
'END;'
using in p_test_value, out l_result;
return l_result;
end;
/
Select Count(1) from Table_Name Where temp_is_number (Column_Name,scale,precision) = 'N';
I am going to start off by apologizing because I don't know how to put my problem into words.
i have a database with about 15000 columns and I want to find every column that has emails stored in it. I've tried searching through column names but that isn't helping because there is so much variation.
i want to do something like this
select column_name from all_tab_cols where data like '%#%.com%
this is on an oracle database but I am accessing the data through tableau.
Thanks,
Aayush
Clarification: I want to find every column that has an email address in it.
This will only find email addresses that end with #something.com, but you are looking for something like what is below. There have been other posts about finding email addresses, it is very difficult to do:
DECLARE
l_cmd VARCHAR2 (2000);
l_found INTEGER;
BEGIN
FOR eachcol IN ( SELECT *
FROM all_tab_cols a
WHERE a.data_type = 'VARCHAR2'
AND owner = 'SEARCHSCHEMANAME'
ORDER BY table_name, column_name)
LOOP
l_cmd :=
'select count(*) c from '
|| eachcol.owner
|| '.'
|| eachcol.table_name
|| ' where '
|| LOWER (eachcol.column_name)
|| q'[ LIKE '%#%.com%' AND ROWNUM = 1]';
EXECUTE IMMEDIATE l_cmd INTO l_found;
IF l_found > 0
THEN
DBMS_OUTPUT.put_line (
RPAD (eachcol.owner || '.' || eachcol.table_name || '.' || eachcol.column_name, 92)
|| ' may contain email addresses'
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (l_cmd);
DBMS_OUTPUT.put_line (SQLERRM);
RAISE;
END;
When I try to run this code, it doesn't show any output and I don't know why.
This procedure takes in a customer ID and displays all the orders
made by the specified customer. It uses a cursor to store the details
of the order and then prints the details.
SET SERVEROUTPUT ON;
create or replace PROCEDURE procedure_CustOrderHistory (cust_id IN number) AS
CURSOR c_CustOrderHistory IS
Select o.order_id, o.order_totalCost, o.order_date, cu.customer_firstName,
cu.customer_lastName, s.staff_firstName, s.staff_lastName, os.order_status
FROM orders o, customer cu, staff s, order_status os
where o.customer_id=cu.customer_id AND s.staff_id = o.staff_id AND
os.order_statusID = o.order_statusID and cu.customer_id = cust_id ;
BEGIN
FOR r_order IN c_CustOrderHistory
LOOP
dbms_output.put_line('Order ID: '||r_order.order_id || ', Order Total Cost: ' || r_order.order_totalCost || 'BHD, Order Date: ' || r_order.order_date || ', Customer Name: ' || r_order.customer_firstName || ' ' || r_order.customer_lastName|| ', Customer Name: ' || r_order.customer_firstName || ' ' || r_order.customer_lastName || ', Order Status: '|| r_order.order_status);
END LOOP;
END;
This anonymous block tests the previous procedure. It asks the user
for an ID and then calls the procedure by passing in the customer ID.
SET SERVEROUTPUT ON;
DECLARE
v_custid number := &customerid;
BEGIN
procedure_CustOrderHistory(v_custid);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('Customer ID not found.');
WHEN OTHERS THEN
dbms_output.put_line('Error! ' || SQLERRM);
END;
A cursor loop doesn't throw NO_DATA_FOUND. So if your query returns no rows the cursor will loop zero times and exit elegantly.
So most likely what has happened is either there are no customer records for the ID you pass at the prompt or there is some other logical problem in the cursor query (say, the customer has no orders).
You can test my theory by adding a counter like this:
create or replace PROCEDURE procedure_CustOrderHistory (cust_id IN number) AS
CURSOR c_CustOrderHistory IS
Select o.order_id, o.order_totalCost, o.order_date, cu.customer_firstName,
cu.customer_lastName, s.staff_firstName, s.staff_lastName, os.order_status
FROM orders o, customer cu, staff s, order_status os
where o.customer_id=cu.customer_id AND s.staff_id = o.staff_id AND
os.order_statusID = o.order_statusID and cu.customer_id = cust_id ;
rec_ctr pls_integer := 0;
BEGIN
FOR r_order IN c_CustOrderHistory
LOOP
rec_ctr := rec_ctr +1;
dbms_output.put_line('#'|| rec_ctr ||' '||
'Order ID: '||r_order.order_id || ', Order Total Cost: ' || r_order.order_totalCost || 'BHD, Order Date: ' || r_order.order_date || ', Customer Name: ' || r_order.customer_firstName || ' ' || r_order.customer_lastName|| ', Customer Name: ' || r_order.customer_firstName || ' ' || r_order.customer_lastName || ', Order Status: '|| r_order.order_status);
END LOOP;
if rec_ctr = 0 then
raise no_data_found;
end if;
END;
This explicitly raises an exception if the loop processed no rows.
".However, even if I enter a valid CustomerID it doesn't display it. Do you have any idea?"
Your query joins four tables. So you need to work through the logic of the query to make sure:
the join conditions are specified correctly
there is matching data in the tables
For instance, does the customer you enter have any orders? If yes, do their orders have a valid order status. Is the order staff ID a valid one?
Getting below error while executing in 12c oracle,but it is working fine when it was in oracle 10.2.0.4 :
Procedure proc_up_dts_product_cat_dynsql failed due to ORA-00920: invalid
relational operator
Here is the procedure :
CREATE OR REPLACE PROCEDURE SEAPROB.proc_up_dts_product_cat_dynsql(tablename IN varchar)
AS
dynamicsql varchar(8000);
ID int;
DTS_Segment_op varchar2(10);
DTS_Segment varchar2(15);
DTS_Segment_where varchar2(255);
DateEntered_op varchar2(10);
DateEntered varchar2(30);
DateEntered_where varchar2(255);
Svc_Name_op varchar2(10);
Svc_Name varchar2(100);
Svc_Name_where varchar2(255);
Product_Category varchar2(75);
Priority int;
combined_status_where varchar2(255);
refdate date ;
CURSOR PrivCursor
IS
SELECT
ID,
DTS_Segment_op,
Nvl(upper(trim(DTS_Segment)),' '),
DateEntered_op,
CASE WHEN dateentered='%' THEN dateentered
WHEN dateentered LIKE '%/%/____' THEN To_Char(To_Date(dateentered,'MM/DD/YYYY'),'YYYY-MM-DD')
WHEN dateentered LIKE '%/%/__' THEN To_Char(To_Date(dateentered,'MM/DD/YY'),'YYYY-MM-DD')
WHEN dateentered LIKE '''%/%/%'' % ''%/%/%''' THEN ''''||To_Char(To_Date(SubStr(dateentered,InStr(dateentered,'''',1,1)+1,InStr(dateentered,'''',1,2)-InStr(dateentered,'''',1,1)-1),'MM/DD/YY'),'YYYY-MM-DD')||''' and '''||To_Char(To_Date(SubStr(dateentered,InStr(dateentered,'''',1,3)+1,InStr(dateentered,'''',1,4)-InStr(dateentered,'''',1,3)-1),'MM/DD/YY'),'YYYY-MM-DD')||''''
ELSE dateentered END AS dateentered,
Svc_Name_op,
Nvl(upper(trim(Svc_Name)),' '),
Product_Category,
Priority
FROM tbl_dts_pt_lookup order by priority desc;
BEGIN
refdate := ADD_MONTHS(to_date(SYSDATE,'dd-mon-yy'),-6) ;
OPEN PrivCursor;
-- Loop through all the rows in the tbl_dts_category_lookup table
FETCH PrivCursor
INTO
ID,
DTS_Segment_op,
DTS_Segment,
DateEntered_op,
DateEntered,
Svc_Name_op,
Svc_Name,
Product_Category,
Priority;
WHILE PrivCursor%found
LOOP
-- Create dynamic SQL
--define case statements for where clause components
combined_status_where := ' where (DTS_Cm_DisputeStatus <>'|| '''C''' || ' OR ( DTS_Cm_DisputeStatus='|| '''C''' || ' AND DTS_CM_CLOSEDATE >= '''||refdate||'''))' ;
dts_segment_where := case when dts_segment='%' then ' and 1=1' else ' and NVL(trim(Replace(Upper(segment),chr(0),''' || ''')),''' || ' '') ' || dts_segment_op || ' ''' || dts_segment || '''' end;
svc_name_where := case when svc_name='%' then ' and 1=1' else ' and NVL(trim(Replace(Upper(dts_cm_servicename),chr(0),''' || ''')),''' || ' '') ' || svc_name_op || ' ''' || svc_name || '''' end ;
dateentered_where := case when dateentered='%' then ' and 1=1'
when dateentered_op='between' then ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') between ' || dateentered
else ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') ' || dateentered_op || ' ''' || dateentered || '''' end ;
dynamicsql := 'update '||tablename||' set product_cat_id=' || cast(id as varchar) ||', product_category =''' || product_category || '''';
--add where clause
dynamicsql := dynamicsql || combined_status_where || dts_segment_where || dateentered_where || svc_name_where;
EXECUTE IMMEDIATE dynamicsql;
COMMIT;
FETCH PrivCursor
INTO
ID,
DTS_Segment_op,
DTS_Segment,
DateEntered_op,
DateEntered,
Svc_Name_op,
Svc_Name,
Product_Category,
Priority;
END LOOP;
CLOSE PrivCursor;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Procedure proc_up_dts_product_cat_dynsql failed due to '||SQLERRM);
END proc_up_dts_product_cat_dynsql;
/
The database hurls ORA-00920: invalid relational operator when we submit a SQL statement with a syntax error in a WHERE clause. Usually it's a typo. This is extremely easy to do in dynamic SQL, because we cannot see the whole statement except at run time.
You haven't posted the generated update statement. Well you can't, as your exception handling doesn't display it. Pro tip: when working with dynamic SQL always log or display the generated statement, in the exception block if nowhere else:
dbms_output.put_line('generated statement:'|| dynamicsql);
So this is just a guess but this line looks suspicious ...
when dateentered_op='between' then ' and TO_CHAR(dts_cm_dateentered,''YYYY-MM-DD'') between ' || dateentered
... because it appears to generate a BETWEEN statement with no AND clause. The BETWEEN operator requires two bounds.
But it could be many things. You may be running with an unusual combination of parameters which generates an invalid statement. You need better logging.