IF-ELSE statement: create a column depending on another one - sql

In the table JAN07, I have a column TEMPO_INTERCORSO (number(10,0)) and I want to create another column ANTE_POST (number(1)) that is '0' when TEMPO_INTERCORSO > 0 and '1' otherwise.
IF (TEMPO_INTERCORSO > 0) THEN
UPDATE JAN07 SET ANTE_POST = 1
ELSE
UPDATE JAN07 SET ANTE_POST = 0
END IF;
I've tried a lot of different ways that you can find on the web (for example the ";" before the ELSE: sometimes there is, sometimes not), but it is still not working.
IF (TEMPO_INTERCORSO = 0) THEN
Report error -
Comando sconosciuto
Some ideas?
ps= I've tried with JAN07.TEMPO_INTERCORSO too!

The following UPDATE query uses CASE...WHEN to achieve what you want:
UPDATE JAN07
SET ANTE_POST = CASE WHEN TEMPO_INTERCORSO > 0 THEN 1 ELSE 0 END

I would rather suggest Virtual Columns introduced in Oracle Database 11g Release 1. A simple CASE statement would do the rest.
For example,
SQL> CREATE TABLE t
2 (
3 TEMPO_INTERCORSO NUMBER,
4 ANTE_POST NUMBER GENERATED ALWAYS AS (
5 CASE
6 WHEN TEMPO_INTERCORSO > 0
7 THEN 1
8 ELSE 0
9 END) VIRTUAL
10 );
Table created.
Now, you need not worry about manually updating the virtual column, it will be automatically generated at run time.
Let's insert the values only in static column and see:
SQL> INSERT INTO t(TEMPO_INTERCORSO) VALUES(0);
1 row created.
SQL> INSERT INTO t(TEMPO_INTERCORSO) VALUES(1);
1 row created.
SQL> INSERT INTO t(TEMPO_INTERCORSO) VALUES(10);
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM t;
TEMPO_INTERCORSO ANTE_POST
---------------- ----------
0 0
1 1
10 1
So, you have your column ANTE_POST with desired values automatically.

Conditional control IF-THEN-ELSE STATEMENT is one statement in PL/SQL. Each statement in PL/SQL ends with semi color. Hence it's written like this:
IF condition THEN
{...statements to execute when condition is TRUE...}
ELSE
{...statements to execute when condition is FALSE...}
END IF; --semi colon at the end
In your code, there is an update statement inside. Therefore, at the end of this statement there must be semi colon. Your code can be written like this:
IF (TEMPO_INTERCORSO > 0) THEN
UPDATE JAN07 SET ANTE_POST = 1; --semi colon
ELSE
UPDATE JAN07 SET ANTE_POST = 0; --semi colon
END IF; --semi colon
Some answer already suggested doing that in pure SQL rather than PL/SQL. Which I agree with.

Related

Binding data to a variable in a CASE WHEN statement

I am writing an oracle PL/SQL compound trigger. In the code I'm querying a single value and putting it into a variable.
From there I check whether the variable is null or not. If it is, I need to assign 0 to another variable, if it isn't I assign 1.
I think this is possible with a CASE WHEN statement.
An example is as follows
//line 23 โ†“
SELECT contract_end INTO contractEnd FROM contract WHERE contract_id = :new.expense_job;
//line 25 โ†“
SELECT CASE WHEN contractEnd IS NOT NULL THEN
contractIDCollection(iterator).ended := 1
ELSE
contractIDCollection(iterator).ended := 0
END
FROM dual;
However, when I do this the compiler throws an error and says that I have not finished the statement.
Is this the correct way to go about doing this?
contractIDCollection is a record with parameters, the definition code is working properly
LINE/COL ERROR
-------- -----------------------------------------------------------------
23/5 PL/SQL: SQL Statement ignored
24/44 PL/SQL: ORA-00905: missing keyword
Do not try to switch from the PL/SQL scope to the SQL scope (with a SELECT statement) to try to assign the variable; just do it all in the PL/SQL scope:
IF contractEnd IS NOT NULL THEN
contractIDCollection(iterator).ended := 1;
ELSE
contractIDCollection(iterator).ended := 0;
END IF;
If you did want to incur the overheads of context-switching (don't, as you do not need to and it is likely to be slower) then you can use:
SELECT CASE WHEN contractEnd IS NOT NULL THEN 1 ELSE 0 END
INTO contractIDCollection(iterator).ended
FROM dual;
or do it all on the line before:
SELECT contract_end,
CASE WHEN contract_end IS NOT NULL THEN 1 ELSE 0 END
INTO contractEnd,
contractIDCollection(iterator).ended
FROM contract
WHERE contract_id = :new.expense_job;

SQL Error subquery must return only one column

I wish to do when the condition of if is met, the values โ€‹โ€‹of the two columns can be changed. I am new to SQL can you plsese help me? My code:
DO
$do$
BEGIN
IF (select * from V1 where starting-lag >= 7)
THEN
INSERT INTO newstart VALUES (starting - 7);
INSERT INTO newend VALUES (starting - 8);
ELSE
INSERT INTO newstart VALUES (lag +1);
INSERT INTO newend VALUES (lag);
END IF;
END
$do$
;
V1(id, starting, ending, lag, lead,newstart,newend)
It returns:
ERROR: subquery must return only one column
LINE 1: SELECT (select * from V1 where (starting-lag) >= 7)
^
QUERY: SELECT (select * from V1 where (starting-lag) >= 7)
CONTEXT: PL/pgSQL function inline_code_block line 3 at IF
I tried to use update but it returns DETAIL: Views that return window functions are not automatically updatable. HINT: To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
I suspect that you want an update statement rather than insert, because you are mentionning that youw ant the values to be changed. That's what an update does, while an insert creates new rows.
The logic you are looking for could be:
update v1
set
newstart = case
when starting - lag >= 7 then starting - 7
else lag + 1
end,
newend = case
when starting - lag >= 7 then starting - 8
else lag
end
There is no need for a do block to implement this logic, a straight query is sufficient.

Pl/Sql Oracle Function in a procedure

I need to make a procedure that needs to update the situation of a student, but I need to use a function that returns 'A' for the approved students, and 'R' for the not approved. After this I need to update the field "Situation" with an 'A' or 'R' that is returned from the function. I already have the function, but I don't have any idea how to make the procedure. Here goes the code of the function:
CREATE OR REPLACE FUNCTION check_grade(grade IN NUMBER,
frequency IN NUMBER) RETURN VARCHAR2 AS
RESULT VARCHAR2(1) DEFAULT '';
BEGIN
IF (grade >= 6) AND (frequency >= 0.75) THEN
resultado := 'A';
ELSE
resultado := 'R';
END IF;
RETURN RESULT;
END;
I think you are over complicating the things. You could do it in pure SQL rather than using PL/SQL function and procedure.
You could use CASE expression, for example:
Test 1
SQL> SELECT
2 CASE
3 WHEN &grade >=6
4 AND &frequency>=0.75
5 THEN 'A'
6 ELSE 'R'
7 END
8 FROM DUAL;
Enter value for grade: 10
old 3: WHEN &grade >=6
new 3: WHEN 10 >=6
Enter value for frequency: 1
old 4: AND &frequency>=0.75
new 4: AND 1>=0.75
C
-
A
Test 2
SQL> SELECT
2 CASE
3 WHEN &grade >=6
4 AND &frequency>=0.75
5 THEN 'A'
6 ELSE 'R'
7 END
8 FROM DUAL;
Enter value for grade: 1
old 3: WHEN &grade >=6
new 3: WHEN 1 >=6
Enter value for frequency: 0.5
old 4: AND &frequency>=0.75
new 4: AND 0.5>=0.75
C
-
R
So, using the same logic in your UPDATE statement:
UPDATE table_name
SET situation = (
CASE
WHEN &grade >=6
AND &frequency>=0.75
THEN 'A'
ELSE 'R'
END)
WHERE situation IS NOT NULL;
Update OP only wants to do it in a procedure:
create or replace procedure pr_update
is
begin
update table_name
set Situation = check_grade(grade, frequency);
end;
/
In the above procedure, put actual table_name in the update statement. grade and frequency are considered as the column names of the table.
See if this help.
create or replace procedure pr_update(v_grade in number, v_frequency in number) is
update tab_name set Situation=check_grade(v_grade,v_frequency);
end;

Simple update set postgres stored procedure

I've a problem trying to make my stored procedure work.
This is my problem:
I have a table with a columns called a, in this column there are telephone numbers.
I have to add 0039 if the number starts with 1,8,3 or 0 (or leave it as is if not) and store the new number in the column b.
This is my code:
CREATE OR REPLACE FUNCTION upg_table() RETURNS void AS $$
BEGIN
IF (substring(a from 0 for 2)!='00')
AND (substring( a from 0 for 1)='3')
OR (substring(a from 0 for 1)='0')
OR (substring(a from 0 for 1)='1')
OR ( substring(a from 0 for 1)='8')
THEN
UPDATE cdr
SET
b = '0039'||a;
ELSE
UPDATE cdr
SET
b = a;
END IF;
END;
$$ LANGUAGE plpgsql;
The error is:
ERROR: the column "a" does not exist
ROW 1: SELECT substring(a from 0 for 2)!='00' AND ...
You code has two errors:
You cannot reference the column a like it was a (non-existent) plpgsql variable. You would have to loop, too. Your approach does not work at all.
You got operator precedence wrong. AND binds before OR.
But most importantly, you don't need a plpgsql function. A plain UPDATE will do the job:
UPDATE cdr
SET b = CASE WHEN left(a, 1) IN ('0', '1', '3', '8')
AND left(a, 2) <> '00'
THEN '0039' || a ELSE a END;
This updates b in all rows, but only some with a changed a.

sql expression pattern matching

I want to check for a pattern in sql such that if there is anything in that expression (or table cell) other than numeric it should return 1. If that whole cell has only numeric values it should return 0
eq:
case when '200290' like [anything other than numbers]
then 1
else o
In SQL Server, you can use something like (I'm not writing the whole function for you):
DECLARE #t varchar(100) = '231321321321'
SELECT CASE WHEN PATINDEX('%[^0-9]%', #t) > 0 THEN 1
ELSE 0 END
SELECT CASE CHARACTERS(OTRANSLATE(<your_string>,'a1234567890','a'))
WHEN 0 THEN 0 ELSE 1 END;
Ex.:
-- BTEQ Enter your SQL request or BTEQ command:
SELECT CASE CHARACTERS(OTRANSLATE('12345','a1234567890','a'))
WHEN 0 THEN 0 ELSE 1 END;
* Query completed. One row found. One column returned.
* Total elapsed time was 1 second.
<CASE expression>
------------------
0
SELECT CASE CHARACTERS(OTRANSLATE('1a23b45c','a1234567890','a')) WHEN 0 THEN 0 ELSE 1 END;
* Query completed. One row found. One column returned.
* Total elapsed time was 1 second.
<CASE expression>
------------------
1