Oracle trigger sequence and lpad - oracle

im trying to insert in my db a 4 charactes password. It is generated by a sequence... the problem im having is that i cant find a way to make that happend. I just find out about triggers, i know the answer to my problem might be there and this is what i have till now :S
CREATE OR REPLACE TRIGGER TRG_PASSWORD
BEFORE INSERT OR UPDATE OF PASSWORD ON USER
FOR EACH ROW
BEGIN
SELECT SEQ_PASSWORD.NEXTVAL
INTO new.PASSWORD := LPAD(:new.PASSWORD,4,'0');
FROM DUAL;
END;
Im new with all these database stuff! plz help! and sorry for my english btw! i know its awful!

Odd password rules as it'd be relatively easy to guess a new user's... but you can do this:
SELECT LPAD(SEQ_PASSWORD.NEXTVAL, 4, '0')
INTO :new.PASSWORD
FROM DUAL;
Or from 11g:
:new.PASSWORD := LPAD(SEQ_PASSWORD.NEXTVAL, 4, '0');
As an alternative to LPAD you could also use TO_CHAR:
:new.PASSWORD := TO_CHAR(SEQ_PASSWORD.NEXTVAL, 'FM0000');
Of course, all of these assume your USER.PASSWORD field is defined as varchar2, not as number.
You probably don't want the 'OF PASSWORD' clause though; that means the sequence will only be used to set the password if that field is set by the insert or update statement, which doesn't seem very intuitive; and resetting the password on update of anything seems unhelpful too.

Related

Is LPAD allowed in PLSQL?

I have a PL/SQL script with a variable called v_credit_hours that is a number data type. I fetch my fields from a cursor and insert them into a table where the credit_hours field is also a number. I need to pad v_credit_hours with leading zeros and end up with four digits before inserting it. So 50 hours should like like 0050. I have this line just before my insert statement.
v_credit_hours := LPAD(ROUND(v_credit_hours), 4, 0);
The problem is that it does not change anything. 50 still comes out as 50. Nothing happens if I change 4 to 10 or if I remove LPAD completely. I tried changing v_credit_hours to v_credit_hours * 8 inside the ROUND, and that altered the result. It is as if Oracle is just ignoring LPAD. It comes out fine in this query, but not when I use PL/SQL. I also tried adding TO_CHAR between LPAD and ROUND, but that did nothing.
SELECT LPAD(ROUND(50), 4, 0) FROM dual;
Can I not use LPAD in this way? I can do it up in my original cursor, but I really only wanted to see the leading zeros in the final output.
Its sorta hard to tell if v_credit_hours is typed as a Number or a Varchar. However, if you do it this way you will get what you want.
DECLARE
v_formatted_credit_hours varchar2(60);
BEGIN
SELECT lpad(round(50),4,0)
INTO v_formatted_credit_hours
FROM dual ;
SYS.dbms_output.put_line( v_formatted_credit_hours) ;
END;
hopefully that helps to shine a little light on your issue.

Oracle SQL: PLS-00049 Bad Bind variable when selecting NEXTVAL from a sequence

So, I'm trying to use JDBC to access my Oracle DB, and I found out that, for the functions in JDBC to return results correctly, I need to make an iterator for my tables. So, after searching around and figuring out what that means, I came up with the following code snippet to get that done:
--create a sequence for use in the trigger
CREATE SEQUENCE accounts_seq;
--make the trigger on insert or update
CREATE OR REPLACE TRIGGER account_pk_trig
BEFORE INSERT OR UPDATE ON accounts
FOR EACH ROW
BEGIN
IF inserting THEN
SELECT : accounts_seq.NEXTVAL INTO : NEW.accountnumber FROM dual;
ELSE IF updating THEN
SELECT : OLD.accountnumber INTO : NEW.accountnumber FROM dual;
END IF;
END IF;
END;
/
And, not only is Oracle SQL Developer putting the dreaded red underline of doom in the space after the semicolon put after end, but also on the forward slash to end the code block. As far as I've seen, this appears to be correct to the Oracle SQL examples of trigger definitions that I've seen... and I'm not sure if this is due to the Oracle SQL Developer not recognizing NEXTVAL as a keyword... because it isn't highlighted like the others are.
After some fiddling around, I realized that the "ELSE IF" opened a new IF statement that I didn't close. But, still getting Bad Bind variable error.
For those of you who would want to make sure that the "accountnumber" field exists in the table "accounts", here's my definition for the "accounts" table.
CREATE TABLE accounts (
accountnumber NUMBER NOT NULL,
routingnumber NUMBER NOT NULL,
acctype VARCHAR2(20),
balance NUMBER (*,2),
ownerid NUMBER,
CONSTRAINT accountnumber_pk PRIMARY KEY (accountnumber)
);
You have two major errors in your PL/SQL code:
First the select : is wrong. You can't just throw in a colon like that. The NEW and OLD records do need a colon, but without a space. :new, not : new.
To store the result of a query in a variable you need:
select accounts_seq.NEXTVAL
INTO :NEW.accountnumber
FROM dual;
But you don't need a SELECT for that, you can use a simple variable assignment:
:NEW.accountnumber := accounts_seq.NEXTVAL;
You also have two END IFs although you only have a single IF
And as documented in the manual it needs to be ELSIF, not ELSE IF
Putting all that together, your trigger should be:
CREATE OR REPLACE TRIGGER account_pk_trig
BEFORE INSERT OR UPDATE ON accounts
FOR EACH ROW
BEGIN
IF inserting THEN
:NEW.accountnumber := accounts_seq.NEXTVAL;
ELSIF updating THEN
:NEW.accountnumber := :OLD.accountnumber;
END IF;
END;
/
As the trigger is declared as BEFORE INSERT OR UPDATE the ELSIF is actually useless, because it can only be insert or updating nothing else. So instead of ELSIF updating THEN you could simply write ELSE

PL/SQL Procedure - Ticket system

I'm trying to make a Procedure in PL/SQL for a ticket system for my website.
I want a simple procedure that saves some data into the database.
It will have name of the user (random VARCHAR2) and a number and the date of today as input.
When this procedure is called it will automatically higher a number in the database (Maybe primary key) and add the input into the database. But I have no idea how to make something like this with the option to have more people access it at once.
Can anyone help please?
For the people that want to know what I have already.
CREATE OR REPLACE PROCEDURE VoegBoeteToe
(v_speler IN number, v_date IN date, v_boete IN number)
IS VoegBoeteToe
DECLARE
v_nextNum NUMBER;
BEGIN
SELECT BETALINGSNR
INTO v_nextNum
FROM BOETES
ORDER BY BETALINGSNR DESC;
v_nextNum := v_nextNum + 1;
INSERT INTO BOETES VALUES(v_nextNum,v_speler,v_date,v_boete);
end;
/
The fourth line of your procedure should be IS instead of IS VoegBoeteToe. In addition, remove the fifth line (DECLARE), which is not needed in a procedure. And use a sequence to derive the sequential number safely.
So, when all's said and done, your procedure should look something like:
CREATE SEQUENCE BOETES_SEQ;
CREATE OR REPLACE PROCEDURE VoegBoeteToe
(v_speler IN number, v_date IN date, v_boete IN number)
IS
BEGIN
INSERT INTO BOETES VALUES(BOETES_SEQ.NEXTVAL,v_speler,v_date,v_boete);
end;
It would also be a very good idea to include the list of field names in the BOETES table into which you're inserting values. This will make life better for anyone who has to maintain your code, and may save you from making a few errors.
Share and enjoy.
You need to create SEQUENCE
CREATE SEQUENCE DUMMY_SEQ
/
Then in Your code You can use something like that:
select DUMMY_SEQ.NEXTVAL into myVar from dual;
First, create a sequence. A sequence generates an ever incrementing number whenever it is invoked. See this for some nice examples. The documentation could be useful too.
CREATE SEQUENCE user_sequence
START WITH 1000 -- your sequence will start with 1000
INCREMENT BY 1; -- each subsequent number will increment by 1
Then,
SELECT user_sequence.NEXTVAL INTO v_nextNum FROM DUAL;

how to get value on other table in trigger on oracle

declare
tgl RENC_DITSEK.TGL_INPUT%TYPE;
thn varchar(10) := :new.tahun + 1;
target RENC_DITSEK.TARGET_2%TYPE;
BEGIN
select TARGET_2 into target from RENC_DITSEK where KODE_RENCANA = :NEW.KODE_RENCANA;
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS') INTO tgl FROM DUAL;
IF UPDATING ('TARGET_2') THEN
INSERT INTO NOTE_LOG VALUES(:NEW.PKP,'',:NEW.INDIKATOR,'Target Tahun '||thn,'',:new.target_2,**target**,tgl,'','0');
END IF;
END;
hi, there is my trigger body. i need a value of TARGET_2 before it updated, but i have no ide to do that. so this is my code, but it error "mutating table". is there a way to do that? please help.
thanks for helping.
it would help if you provide the table and the trigger definitions.
e.g. what table are you creating the trigger on? Is KODE_RENCANA the primary key of the table?
If the answer to the above questions is Yes, then you don't need to execute a SELECT statement, since you could get the value of TARGET_2 using :OLD.TARGET_2 for the record you're updating.
If KODE_RENCANA is not the primary key, and it is actually a field that could be updated, and you want to retrieve another record in the same table given the new KODE_RENCANA value, then the problem is more complicated, which I would not recommend using a trigger to handle, instead, try creating a stored procedure and call the stored procedure to perform the update.
cheers.

How do I run procedure in oracle with some date manipulation sql in it

I have created a procedure in oracle as follows:
create or replace PROCEDURE SP_X_AVERAGE
(
profile out SYS_REFCURSOR,
rx out SYS_REFCURSOR,
)
as
BEGIN
open profile for
select
avg(to_number(profile_netassets)) AS netassets
from
fgp;
open rx for
select
avg(to_number(a_price)) as twr
from
r_x
where
gq_date <= add_months(to_date(sysdate, 'mm/dd/yyyy'), -12);
END SP_X_AVERAGE;
It doesn't run, giving the following error:
ORA-01843: not a valid month
If I remove the where condition in the second sql then it runs successfully.
Altering a session using an sql in the same procedure doesnot work too.
Please help.
I am running this procedure in sql-developer (ubuntu Oneiric 11)
SYSDATE is already a DATE so you don't need to apply TO_DATE() to it. However, more recent versions of Oracle are tolerant of such things and handle them gracefully.
So that leaves the matter of r_x.gq_date: what data type is that? If it is a string then the chances are you have values in there which will not cast to a date, or at last don't match your default NLS_FORMAT.
"we have to keep it as "VARCHAR2(40 BYTE)" it is having date in it like this : '1/2/2003'"
Bingo. Is that the same as your NLS_DATE_FORMAT? If not you will need to cast the column:
to_date(gq_date, 'mm/dd/yyyy') <= add_months(sysdate, -12);
This may not solve your problem if the column contains strings which aren't in that format. This is a common side-effect of using strings to hold things which aren't strings.

Resources