I'am creating dynamic tables from java. What I want is that I want to create a trigger on every new table added which will just use the sequence to populate the primary key(serial_no) which is common in every table.How to achieve this ???
EDIT:
I have tried this code but I'am getting a message "procedure created with compilation errors"
create or replace procedure "TRIGGER_CALL" (trigger_name IN VARCHAR2, table_name IN VARCHAR2, sno IN NUMBER) as begin CREATE SEQUENCE abc MINVALUE 1 MAXVALUE 10000 INCREMENT BY 1 START WITH 141 CACHE 20 NOORDER NOCYCLE; CREATE OR REPLACE TRIGGER trigger_name before insert on table_name for each row begin select s_no.nextval into :new.sno from dual; end; end;
EDIT2:
My code
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
l_seq_name VARCHAR2(30);
BEGIN
--SELECT '1'
--INTO l_dummy
--FROM all_tables
-- WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_seq_name := p_table_name || 's_no';
EXECUTE IMMEDIATE 'CREATE SEQUENCE l_seq_name start with 1 increment by 1 ';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT l_seq_name.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
Please check following code:
CREATE SEQUENCE my_sequence;
/
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
BEGIN
-- Validate if a p_table_name is a valid object name
-- If you have access you can also use DBMS_ASSERT.SQL_OBJECT_NAME procedure
SELECT '1'
INTO l_dummy
FROM all_tables
WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
CREATE TABLE my_test(sno NUMBER);
/
BEGIN
trigger_call('my_test');
END;
/
Important notes:
Usage of AUTHID CURRENT_USER eliminates the "insufficient privileges" problem. For reference see: Execute Immediate within a stored procedure keeps giving insufficient priviliges error
Because the dynamic sql simply concatenates the input parameter it needs to be validated to protect against SQL Injection. See also DBMS_ASSERT.
Because of point 2. I used table name to build trigger name.
I am trying to execute a procedure in oracle, but i get a exception while executing the procedure.Please help me where i am wrong.
Error :
java.sql.SQLException: ORA-06550: line 1, column 36:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( ) , * # % & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator multiset member submultiset
The symbol ")" was substituted for ";" to continue.
Procedure :
CREATE OR REPLACE PROCEDURE "TEST_101"."AVG_UNLOADING"
(
P_CODE IN VARCHAR2,
P_DATE IN VARCHAR2,
P_VANID IN NUMBER,
P_CURSOR OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN P_CURSOR
FOR
select CARGO_NAME,IMP_EXP_NAME,'TEMP_CARGO_Import',ROUND(SUM(QTY)/((((extract(day from max(END_TIME)-DISCHRG_CMNCD_ANCHRG_TM)*(24*60))+
(extract(day from max(END_TIME)- DISCHRG_CMNCD_ANCHRG_TM)*(60)) + (EXTRACT(DAY FROM max(END_TIME)- DISCHRG_CMNCD_ANCHRG_TM)))-DELAYS)/(24*60))) QTY
from(SELECT (SELECT C.CARGO_CATEGORY_NAME FROM IPT_CARGOMASTER C WHERE C.CARGO_CODE =LL.CARGO_CODE )CARGO_NAME,IL.IMP_EXP_NAME,CASE L.CARGO_TYPE_CODE WHEN 'VC001' THEN LL.DISCHARGE_QUANTITY WHEN 'VC002' THEN LL.QUANTITY_GMT WHEN 'VC004' THEN LL.QUANTITY_GMT
else LL.DISCHARGE_QUANTITY end QTY ,L.DISCHRG_CMNCD_ANCHRG_TM,LL.END_TIME ,(SELECT SUM(T3.TOTAL_TIME) FROM IPT_LOADUNLOADDELAYLINES T3 WHERE T3.ID = L.ID AND T3.MINUS_DELAY_HOURS = 'true') AS DELAYS
,LL.LINE_ID,L.VAN_ID FROM IPT_LOADINGUNLOADING L JOIN IPT_LOADUNLOADOPERATIONLINES LL ON L.ID=LL.ID LEFT JOIN IPT_IMPORTEXPORTFORM I ON I.VAN_ID=L.VAN_ID JOIN IPT_IGMEPCARGOLINES IL ON I.ID=IL.ID AND LL.CARGO_CODE=IL.CARGO_CODE
where L.PORTDETAIL_CODE= P_CODE and I.PORTDETAIL_CODE=L.PORTDETAIL_CODE and IL.IMP_EXP_NAME like '%KKR%' AND LL.END_TIME<=TO_TIMESTAMP(TO_CHAR(P_DATE || ' 06:59'),'dd/MM/yyyy HH:MI')
and L.VAN_ID in (P_VANID )
)t group by CARGO_NAME, IMP_EXP_NAME, 'TEMP_CARGO_Import',DISCHRG_CMNCD_ANCHRG_TM,DELAYS;
END AVG_UNLOADING;
Executing procedure
stkagentlist = "{call AVG_UNLOADING(?,?,?,?}";
callableStatement = conn.prepareCall(stkagentlist);
callableStatement.setString(1, portCode);
callableStatement.setString(2, dt );
callableStatement.setString(3, vanids );
callableStatement.registerOutParameter(4, OracleTypes.CURSOR);
callableStatement.executeUpdate();
stkagentlist = "{call AVG_UNLOADING(?,?,?,?}";
I think in this statement the closing round bracket is missing, it should be:
stkagentlist = "{call AVG_UNLOADING(?,?,?,?)}";
I have a function plsql, run function in plsql return cursor have data But i call this function in java problem return resultset falase Help me handling problem this
enter code here
This function plsql
FUNCTION get_canh_bao(
p_toolid in varchar2)
RETURN sys_refcursor IS
s varchar2(4000);
ptype varchar2(1000);
pday varchar2(1000);
psql varchar2(1000);
pcreate varchar2(1000);
re sys_refcursor;
pwhere varchar2(1000);
BEGIN
--
pwhere := '';
s := 'select b.TYPE_REPORT, b.DAY_NHAPLIEU, a.sql_cmd, a.name_createdate'
||' from cpcdata.tbl_config_nhaplieu a'
||' left join cpcdata.tbl_mainmenu b'
||' on a.tool_id = b.ID '
||' where b.show_all = 0 and b.flag = 1 and b.ID = :toolid';
execute immediate s INTO ptype, pday, psql, pcreate using p_toolid;
-- Tinh ngay canh bao
if (INSTR(psql,'where') > 0 ) then
pwhere := ' and ';
else
pwhere := ' where ';
end if;
s := psql ||pwhere||pcreate||' between :aDate AND :bDate';
CASE
WHEN ptype = 'day' THEN
s := psql ||pwhere|| ' to_char('||pcreate||',''dd/mm/yyyy'') = to_char(sysdate - '||pday||',''dd/mm/yyyy'')';
open re for s;
WHEN ptype = 'week' THEN
open re for s USING TRUNC (sysdate, 'iw'), TRUNC(sysdate, 'iw') + 7 - 1/86400- pday;
WHEN ptype = 'month' THEN
open re for s USING TRUNC (sysdate, 'mm'), to_date(LAST_DAY(TRUNC (sysdate, 'mm')) + 1 - 1/86400 - pday,'dd/mm/yyyy');
WHEN ptype = 'quy' THEN
open re for s USING TRUNC (sysdate, 'Q'), to_date(add_months(trunc(sysdate,'Q'),3)- 1 - pday, 'dd/mm/yyyy');
WHEN ptype = 'year' THEN
open re for s USING TRUNC (sysdate , 'YEAR'), to_date(ADD_MONTHS(TRUNC (SYSDATE,'YEAR'),12) - 1 - pday, 'dd/mm/yyyy');
ELSE return null;
END CASE;
dbms_output.put_line(''||s);
RETURN re ;
exception when others then
declare
s_err varchar2(2000);
str varchar(2000);
c_err sys_refcursor;
begin
s_err := 'loi khi lay du lieu '|| sqlerrm;
str := 'select '||s_err||' from dual';
open c_err for str;
return c_err;
end;
END;
This is code java
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn =
DriverManager.getConnection("jdbc:oracle:thin:#***:**:**",
"***", "***");
System.out.println("Connect db success ! ");
ArrayList arr = new ArrayList();
String sql = "{? = call get_canh_bao(?)}";
CallableStatement cs = conn.prepareCall(sql);
cs.registerOutParameter(1, OracleTypes.CURSOR);
cs.setString(2, "502");
cs.executeQuery();
ResultSet rs = (ResultSet)cs.getObject(1);
System.out.println("------------ResultSet---------------"+rs.next());
while (rs.next()) {
System.out.println("a");
String[] str =
{"1" };
arr.add(str);
}
System.out.println("size="+arr.size());
Result when run code in java
Connect db success !
------------ResultSet---------------false
size=0
The problem is likely caused by one of the date conversions that uses an implicit date format.
Oracle does not have a "default" date format, the date format is always dependent on the client. Your Java client and database IDE likely have different defaults.
But don't fix the code by changing the client settings. Instead, clean up the date functions and remove all date to character conversions.
In general, when working with dates, TO_DATE and TO_CHAR should almost always be avoided. If a date needs to be manipulated, there is almost surely a date function
that does not require a conversion. And dates should always be stored as dates, so you should not need to convert back and forth from the table.
The biggest problem is probably this:
pcreate varchar2(1000);
Change that to a date. If for some reason a.name_createdate is a string, then at least make the conversion explicit.
You're populating pcreate (a string) from tbl_config_nhaplieu.name_createdate without specifying a format, so (assuming it is a date column) it is possible that the format could be different within the Java client environment, e.g. if it defaults to mm/dd/yyyy or dd-mon-yyyy instead of dd/mm/yyyy.
Later you compare it directly to dates:
s := psql || pwhere || pcreate || ' between :aDate and :bDate';
but without quoting, so you'll get a query like this:
where 01/02/2016 between :aDate and nDate
Elsewhere you convert it back to a date assuming dd/mm/yyyy format (which you didn't specify when you encoded it as a string earlier, so there's no reason it should match that format):
s := psql || pwhere || ' to_char(' || pcreate || ',''dd/mm/yyyy'') = to_char(sysdate - ' || pday || ',''dd/mm/yyyy'')';
but it's not quoted there either, so you'll get something like this:
where to_char(01/02/2016,'dd/mm/yyyy') = to_char(sysdate - 3,'dd/mm/yyyy')
which will fail.
Then there's this:
to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - pday, 'dd/mm/yyyy')
which may not give the result you expect. For example:
select to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - 0, 'dd/mm/yyyy') as test
from dual;
which gives me 31-JUL-2016 in SQL*Plus and SQL Developer but 31/07/0016 in PL/SQL Developer, due to different nls_date_parameter settings.
As Jon said, you need to clean up all of the date handling.
I'm using SQL Case in my select and in group by clause and I'm working in JAVA. Whenever I execute my java program it says:
Column 'dbo.JOHN_Dashboard.Log_Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
My Query is:
SELECT EP.Site_Code AS [Site_Code], DB.[Site] AS [Site], DB.[Utility] AS [Utility],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date]
END AS [log_date],
SUM(CASE WHEN DB.[value] >= 0 THEN DB.[value] ELSE 0 END) AS [value],
SUM(CASE WHEN DB.[Cost] >=0 THEN DB.[cost] ELSE 0 END) AS [Cost],
SUM(CASE WHEN DB.[CO2] >=0 THEN DB.[CO2] ELSE 0 END) AS [CO],
MT.[Meter_type_name] AS [Meter Type],
MN.[Meter_Name] AS [Meter Name],
U.[Unit_Name] AS [Units],
EP.EnergyPoint_ID AS [Meter_ID],
EP.Parent_ID AS [Parent],
EP.Meter_Description AS [Meter_Description]
FROM [dbo].[JOHN_Dashboard] DB
INNER JOIN [dbo].[EnergyPoints] EP ON DB.[EnergyPoint_ID] = EP.[EnergyPoint_ID]
INNER JOIN [dbo].[Meter_Types] MT ON MT.[Meter_Type_ID] = EP.[Meter_Type_ID]
INNER JOIN [dbo].[Meter_Names] MN ON MN.[Meter_Name_ID] = EP.[Meter_Name_ID]
INNER JOIN [dbo].[Units] U ON U.[Unit_ID] = EP.[Unit_id]
WHERE [log_date] >= ? AND [Log_Date] < DATEADD(DAY, 1, ?)
AND ( ? IS NULL OR EP.Energypoint_ID = ?)
GROUP BY EP.Site_Code, DB.[Site], DB.[Utility], MT.[Meter_type_name],
MN.[Meter_Name], U.[Unit_Name], EP.[EnergyPoint_ID],
EP.[Parent_ID], EP.[Meter_Description],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date] END ;
The parameters i'm passing are:
'Week'
'2016-05-16'
'2016-05-22'
6044
6044
'Week'
Note: This query runs without error in SQL Management Studio.
As requested here is a reworked version of your code using a sub-query before grouping. Since I don't have your database I can't guarantee that I have everything exactly right but give this a try.
I recommend always using a sub-query when your group by has complicated logic that will be repeated in the select. Some people would probably drop the second criteria and just say whenever the group by has complicated logic.
SELECT sub.Site_Code, sub.[Site], sub.[Utility], sub.[Meter Type],
sub.[log_date],
SUM(sub.[value]) as [value],
SUM(sub.[Cost]) as [cost],
SUM(sub.[CO]) as [CO],
sub.[Meter Name], sub.[Units], sub.[Meter_ID],
sub.[Parent], sub.[Meter_Description]
FROM (
SELECT EP.Site_Code AS [Site_Code], DB.[Site] AS [Site], DB.[Utility] AS [Utility],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date]
END AS [log_date],
CASE WHEN DB.[value] >= 0 THEN DB.[value] ELSE 0 END AS [value],
CASE WHEN DB.[Cost] >=0 THEN DB.[cost] ELSE 0 END AS [Cost],
CASE WHEN DB.[CO2] >=0 THEN DB.[CO2] ELSE 0 END AS [CO],
MT.[Meter_type_name] AS [Meter Type],
MN.[Meter_Name] AS [Meter Name],
U.[Unit_Name] AS [Units],
EP.EnergyPoint_ID AS [Meter_ID],
EP.Parent_ID AS [Parent],
EP.Meter_Description AS [Meter_Description]
FROM [dbo].[JOHN_Dashboard] DB
INNER JOIN [dbo].[EnergyPoints] EP ON DB.[EnergyPoint_ID] = EP.[EnergyPoint_ID]
INNER JOIN [dbo].[Meter_Types] MT ON MT.[Meter_Type_ID] = EP.[Meter_Type_ID]
INNER JOIN [dbo].[Meter_Names] MN ON MN.[Meter_Name_ID] = EP.[Meter_Name_ID]
INNER JOIN [dbo].[Units] U ON U.[Unit_ID] = EP.[Unit_id]
WHERE [log_date] >= ? AND [Log_Date] < DATEADD(DAY, 1, ?)
AND ( ? IS NULL OR EP.Energypoint_ID = ?)
) sub
GROUP BY sub.Site_Code, sub.[Site], sub.[Utility], sub.[Meter Type],
sub.[Meter Name], sub.[Units], sub.[Meter_ID],
sub.[Parent], sub.[Meter_Description], sub.[log_date];
code in jsp page
cs=conn.prepareCall("{call held('"+session.getAttribute("roll")+"')}");
cs.executeUpdate();
in oracle database procedure is as
create or replace procedure "Held"
(s in Varchar2)
l_col_name varchar2(30);
begin
SELECT SUBJECTCODE
into l_col_name
FROM table02
WHERE SERIALNUMBER = '1';
execute immediate
'UPDATE TABLE01 SET '|| l_col_name || ' = '
|| l_col_name || ' + 1 WHERE Rollno = s'
;
end;
the following is the error
java.sql.SQLException: ORA-00904: "S": invalid identifier ORA-06512: at "ROHIT.HELD", line 12 ORA-06512: at line 1
please rectify it
i am trying to take the value of session ie from code in jsp and trying to use it in oracle database ....
i have used s as variable to store that value and used it in where clause
suggest a solution
I don't know if the jsp side is correct, but you clearly have a bug in your procedure.
When ORA-00904 occurs, you must enter a valid column name as it is
either missing or the one entered is invalid.
Here, your statement WHERE Rollno = s is understand as 'where column rollno is equal to column s', but the column s doesn't exist. I suppose you just have to move s out of the string.
execute immediate
'UPDATE TABLE01 SET '|| l_col_name || ' = '
|| l_col_name || ' + 1 WHERE Rollno = ''' || s || ''''
;