Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
There is a schema say 'A' in which there is a package called 'B' in which this is a function (below). In this function 'TIMESTMAP' is used which while compiling in 11g is giving error. I want to create a public synonym for TIMESTAMP. Can anyone please provide me the script for the same.
FUNCTION generate_random_number
Return Number
IS
l_seq_no VARCHA2(6)
l_sys_date CHAR(10)
BEGIN
SELECT LTRIM(TO_CHAR(TIMESTAMP.NEXTVAL,'000000'), ' ')
INTO l_seq_no
from DUAL;
SELECT TO_CHAR(SYSDATE, 'H24:MI:SS')
INTO l_sys_date
from DUAL
TIMESTAMP is a reserved word so it will be interpreting your code as TIMESTAMP being a datatype (so I guess the error your getting is nextval must be declared or something). So whilst you can create a sequence called TIMESTAMP, it is extremely silly to do so. you should rename the synonym. Failing that you can create a synonym (public or private) with a different name.
eg:
SQL> create sequence timestamp start with 1;
Sequence created.
SQL>
This sequence can be used in SQL but it cannot be used in PL/SQL (which is what the OP is trying to do). The function won't compile (with a PL-00302 error). So we must create a synonym for it:
SQL> create synonym t for timestamp;
Synonym created.
then use T in your code.
your code also has numerous other typos. missing ; and mistyped varchar2. Finally char(10) for the time will mean its blank padded with 2 trailing spaces (as the length of the string will be 8 chars).
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last year.
Improve this question
i am trying to create a table in oracle sql as shown below
create table Employee
(
S.NO NUMBER(2) PRIMARY KEY,
NAME VARCHAR(20),
DESIGNATION VARCHAR(20),
BRANCH VARCHAR(20)
)
it shows an error "only simple column names allowed here"
please help!!
Generally, it's a bad idea to name columns like that because it might (and will) make your code less readable.
But if you really-really-really need it, you can use quotes
create table test(
"s.no" number
);
dbfiddle
Almost every character can be used in an identifier if and only if you're using quotation at table definition. Let's see an example.
SQL> create table t1 ("S.NO" number, "!##$%^&*()" varchar2(10));
Table created.
SQL> desc t1;
Name Null? Type
----------------------------------------- -------- ----------------------------
S.NO NUMBER
!##$%^&*() VARCHAR2(10)
From now on, you have to use quotation to wrap these weird identifiers in every statement you used.
SQL> insert into t1 ("S.NO", "!##$%^&*()") values (1, 'abc');
1 row created.
SQL> select "!##$%^&*()" from t1 where "S.NO" = 1;
!##$%^&*()
----------
abc
Normally, we don't use quotation to define column or table identifier, simply because it's error prone.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
select 'open' as "documentno" from c_order
union all
select documentno as "documentno" from c_invoice
.This is not working in oracle.
i need a query that works in both oracle and postgres
You have not provided enough information to answer your question.
My guess is that you want to include columns in a union that do not have the same data type and are looking for a way to cast a number to a character value (again I'm guessing because you didn't tell us what data type documentno is).
The following works in Oracle and Postgres:
select 'open' as "documentno" from c_order
union all
select cast(documentno as varchar(20)) as "documentno" from c_invoice;
However: the first part of the union does not make sense. Why are your retrieving the same constant value for each and every row in c_order without any additional information from that table?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have written stored procedure and it takes long time when i call it.
I use temporary table in 'SP'.
it can be reason ??
CREATE OR REPLACE PROCEDURE TEST_SP
IS
BEGIN
INSERT INTO MYTEMP_table (A, B )
( SELECT id AS CUSTOMER_NO,
ACC_NO AS ACCOUNT_NO
FROM myTable );
UPDATE MYTEMP_table
SET MYTEMP_table.A =
( SELECT MIN (BRH_DATE)
FROM CUSTOMER,)
UPDATE MYTEMP_table
SET MYTEMP_table.B =
( SELECT MIN (SUBSTR (ENTRY_DATE, 0, 8))
FROM INFO)
.......
MYTEMP_table is temporary table.
This code snippet looks woefully incomplete. Seems odd that you are filling the temp table with one query:
select id, acc_no from myTable
and then wiping out all columns with a single value:
UPDATE MYTEMP_table
SET MYTEMP_table.A =
( SELECT MIN (BRH_DATE)
FROM CUSTOMER,)
Your post is not clear, but hopefully you are using a global temporary table (Memory based) rather than a physical table meant for temporary storage.
Multiple writes to the same rows is a sure-fire way of slowing down the works (Much more-so in a physical table, but still slow either way). If possible, consider the following:
Use analytic functions or a more complex initial query to get all your writing done up front...
If you're not comfortable/familiar with running/reading explain plans, try running each SQL statement in a SQL Editor manually to assess their individual performance...
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have finished my first real PL/SQL stored proc, this stored proc works as expected. I am new to PL/SQL, could you please point anything wrong or bad coding ?
This code is assuming a naming convention, for example, 't_company' table will use 'companyId' as its primary key and its type is number.
Thank you very much.
create or replace
package body test_erp AS
procedure init_data is
begin
logMessage('procedure init_data');
SAVEPOINT do_insert;
insert into t_company(companyId, companyName) values(gen_key('t_company'), 'IBM');
COMMIT;
exception
WHEN OTHERS THEN
rollback to do_insert;
logMessage('roll back , due to '|| SQLERRM);
end init_data;
end test_erp;
It will call this function
create or replace
function gen_key(tblName varchar2)
return number is
l_key number := 1000;
l_tmpStr varchar(2000); -- not good, how to fix it ?
begin
l_tmpStr := substr(tblName, 3, length(tblName));
EXECUTE IMMEDIATE ' SELECT CASE WHEN MAX('||l_tmpStr||'Id) IS NULL THEN 1000 ELSE MAX('||l_tmpStr||'Id)+1 END FROM '|| tblName into l_key;
logmessage('gen primary key '|| tblName ||' '||l_key);
return l_key;
end;
Your key_gen procedure is rather problematic. Generating keys by doing a MAX(key)+1 is slow and will not work in a multiuser environment. Assuming you have two users, it is relatively easy for both users to see the same MAX(key) and try to insert rows with the same primary key.
Oracle provides sequences in order to efficiently generate primary keys in a multi-user environment. You would be much better served using sequences to generate your keys. Conventionally, you would create one sequence per table, i.e.
CREATE SEQUENCE company_seq;
Your INSERT statement would then be something like
insert into t_company(companyId, companyName) values(company_seq.nextval, 'IBM');
Or you could create a trigger on the table to automatically populate the primary key.
Additionally, while it is fine to catch exceptions in order to log them, you really want to re-raise that exception so that the caller is aware that the INSERT failed.
Using function in your case gen_key is very slow and it's incorrect database-written and also very inefficiently.
So my advice is to create SEQUENCE that is generally used for this.Then you should create TRIGGER for generating new PK for each INSERT or directly add it with NEXTVAL.
So, your SEQUENCE can looks like this:
CREATE SEQUENCE YOUR_COMP_SEQ
MINVALUE 1
MAXVALUE 999999
START WITH 1
INCREMENT BY 1
NOCACHE
;
Then i recommend to you use meant TRIGGER:
CREATE OR REPLACE TRIGGER AUTOSET_ID_COMP
BEFORE INSERT ON t_company
FOR EACH ROW
BEGIN
SELECT YOUR_COMP_SEQ.NEXTVAL INTO :NEW.companyId FROM DUAL;
END;
And finally just call query:
INSERT INTO t_company(companyName) VALUES('SomeValue');
If you don't want to create TRIGGER so you can do it directly like this:
INSERT INTO t_company(companyId, companyName)
VALUES(YOUR_COMP_SEQ.NEXTVAL, 'SomeValue');
Note: Of course, you can create for every TABLE its own SEQUENCE and then use TRIGGERS for each TABLE.
Note 2: Sequences are very good but there is some problem that for example you added to table 20 rows, so IDs are 1,2,3, ... etc. and for example you will delete 15. row and since this ID 15 you can't use, anymore.
Update:
Answer and Solution is updated after a little discussion with #Ben, thanks.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a table by name AN_REMEDIATION_MATRIX loaded through a plsql package.
I have a log table MD_RUNS_STEP with the below structure:
STEP_ID NOT NULL NUMBER
RUN_TYPE VARCHAR2(10)
RUN_START DATE
RUN_END DATE
RUN_SUCCESS NUMBER
USERNAME VARCHAR2(30)
RUN_ID NOT NULL NUMBER
RUN_ROLLBACK NUMBER
STEP_ID_PREV NUMBER
SYSID VARCHAR2(9)
PROGRESS VARCHAR2(500)
STAT_RECS NUMBER
STAT_CPU NUMBER
STAT_TIME NUMBER
STAT_SEQ_READ NUMBER
STAT_SCT_READ NUMBER
Now I need to load this log table with the above values when my package is being executed.
How can this be done? can anyone please help me I have no idea about how it works as I am new to oracle.
Looking forward for the reply.
Thank you
There is no Oracle specific way/setting of automatically populating this log table. Since It is specific to your application, once you understand what these columns mean, you can add code to your pl/sql procedure to get the logs as needed. Some of the columns are straightforward and this is usually how the code looks.
Let us say your current procedure current looks something like this..
create or replace procedure p_INS_AN_REMEDIATION_MATRIX
as
BEGIN
insert into p_INS_AN_REMEDIATION_MATRIX(.....) values (.....);
update p_INS_AN_REMEDIATION_MATRIX set... where ...;
commit;
END;
/
Let's take some log columns..(STEP_ID, RUN_START, RUN_END , RUN_SUCCESS).
Your code would look something like this after the change
create or replace procedure p_INS_AN_REMEDIATION_MATRIX
as
procedure add_new_log (i_step_id) is
pragma autonomous_transaction;
begin
insert into MD_RUNS_STEP (i_step_id, run_start)
values (i_step_id, sysdate);
commit;
end;
procedure update_status (i_step_id, i_status)
.....
end;
v_step_id number;
BEGIN
select run_step_id_seq.nextval into v_step_id from dual;
add_new_log(v_step_id);
insert into p_INS_AN_REMEDIATION_MATRIX(.....) values (.....);
update p_INS_AN_REMEDIATION_MATRIX set... where ...;
commit;
update_status(i_step_id,'SUCCESS'); --will set the load finish time as well.
EXCEPTION
WHEN OTHERS THEN
update_status(i_step_id,'FAILURE');
--RAISE, SEND ERROR EMAIL Based on your logic.
END;
/
as #DCookie pointed out (+1) , Autonomous transaction is a perfect use-case for logging like this. Your main transaction is not impacted and you can, at any point, see the latest up-to-date status of the run.
Usually, you might have existing packages that does all this updates and you'll probably need to just call these APIs. Ask around or look at one the currently running loads.
Do you need to perform periodic inserts into this table as your package is executing, and need the ability to see the progress from another session?
If so, you might look into the PRAGMA AUTONOMOUS_TRANSACTION statement. Put your insert statement into a function defined with this PRAGMA in it, and you can commit your insert independent of your package. Call your function as needed in your package.