I'd appreciate some help on this topic since I am making my first steps into PL/SQL:
When trying to create a function, I get an error: "Table or view does not exist" for all 5 Select statements (and for the statement in the cursor declaration as well). I am sure all tables exist.
Many thanks in advance.
CREATE OR REPLACE FUNCTION ZINSKALK (vtid IN NUMBER, intart IN INTEGER)
RETURN NUMBER
IS
j INTEGER := 0;
p NUMBER := 1;
q NUMBER := 0;
t NUMBER := 1;
r NUMBER := 0;
lz INTEGER := 0;
modusvn INTEGER := 0;
w1 NUMBER := 0;
w2 NUMBER := 0;
i INTEGER := 0;
TYPE ARRAY_TYP IS VARRAY (200) OF NUMBER (10, 2);
RARRAY ARRAY_TYP;
CURSOR C1
IS
SELECT vtobslpos.anzahl, vtobslpos.betrag
FROM vtobsl, vtobslpos
WHERE vtobsl.sysid = vtobslpos.sysvtobsl
AND vtobsl.sysid IN
(SELECT MAX (vtobsl.sysid)
FROM vtobsl
WHERE vtobsl.sysvt = vtid AND vtobsl.rang = 100)
ORDER BY vtobslpos.rang ASC;
BEGIN
SELECT SUM (vtobslpos.anzahl)
INTO lz
FROM vtobslpos, vtobsl
WHERE vtobslpos.sysvtobsl = vtobsl.sysid
AND vtobsl.sysvt = vtid
AND vtobsl.sysid IN (SELECT MAX (sysid)
FROM vtobsl
WHERE sysvt = vtid AND rang = 100);
SELECT vtobsl.modus
INTO modusvn
FROM vtobsl
WHERE vtobsl.sysid IN (SELECT MAX (sysid)
FROM vtobsl
WHERE sysvt = vtid AND rang = 100);
SELECT bgextern
- sz
+ (CASE intart
WHEN 1 THEN 0
WHEN 2 THEN - (sz2 + disagio)
WHEN 3 THEN (sz2 + disagio - provision)
ELSE 0
END)
INTO W1
FROM vt
WHERE sysid = vtid;
SELECT rw + rsv
INTO w2
FROM vt
WHERE sysid = vtid;
i := (CASE WHEN modusvn = 0 THEN 1 ELSE 0 END);
RARRAY (1) := -w1;
RARRAY (lz + 1) := w2;
FOR x IN C1
LOOP
FOR y IN 1 .. x.anzahl
LOOP
i := i + 1;
RARRAY (i) := RARRAY (i) + x.betrag;
END LOOP;
END LOOP;
WHILE ABS (p) >= 0.001
LOOP
p := 0;
q := 0;
j := 0;
FOR z IN 1 .. lz + 1
LOOP
j := j + 1;
p := p + RARRAY (j) * POWER (t, j - 1);
q := q + (j - 1) * RARRAY (j) * POWER (t, j - 2);
END LOOP;
t := t - p / q;
END LOOP;
r := 1200 / t - 1200;
RETURN r;
EXCEPTION
WHEN OTHERS
THEN
RETURN 0;
END;
I assume the table belong to another schema than the schema into which your function is compiled. If you have granted select on these table via role rather than directly, Oracle will give you an ORA-00942.
See this stackoverflow question for more information.
Did you compile the procedure on the same schema of the tables? If you use toad try to press F4 button when cursor is on table name or try to launch the command "desc tablename"
Try describing the tablename with same credentials in the same schema with which you are trying to compile/execute the function.
desc tablename
Related
So here is the question:
Write code to take in an id and determine if the check digit is correct
UPDATED CODE:
Set SERVEROUTPUT ON
DECLARE
val_num NUMBER := '&user_input';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num*10);
for x in 1..length(conv_string) loop
y := to_number(substr(conv_string, -x, 1));
if mod(x,2) = 0 then
y := y * 2;
if y > 9 then
y := y - 9;
end if;
end if;
holder := holder + y;
end loop;
dbms_output.put_line ('Check is '||(11-Mod(holder, 11)));
END luhn;
/
SET SERVEROUTPUT ON
The return is:
SQL> # loop
Enter value for user_input: 036532
old 2: val_num NUMBER := '&user_input';
new 2: val_num NUMBER := '036532';
Check is 2
It should be 6
Before actual execution
SET SERVEROUTPUT ON
to enable SQL*Plus to fetch database output buffer.
Here is solution: https://community.oracle.com/thread/837639?start=0&tstart=0
There are lots of different variations of the luhn algorithm, so looking at these implementations and your (I think incomplete) description in the comments I think this may be fairly close to what you are looking for, and gives the correct checksum for 036532 as per your initial question.
Hope it is helpfull
Set SERVEROUTPUT ON
DECLARE
val_num number := '036532';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num);
FOR X IN 1..LENGTH(CONV_STRING) LOOP
Y := TO_NUMBER(SUBSTR(CONV_STRING, -X, 1));
IF ((X+1) > 10) THEN
Y := Y * 10;
ELSE
Y := Y * (X + 1);
END IF;
IF (Y >= 10) THEN
HOLDER := HOLDER + TO_NUMBER(substr(TO_CHAR(Y), 1, 1)) + TO_NUMBER(substr(TO_CHAR(Y), 2, 1));
ELSE
HOLDER := HOLDER + Y;
END IF;
END LOOP;
HOLDER := MOD(HOLDER, 11);
Holder := 11 - mod(holder, 11);
dbms_output.put_line ('Check is '|| holder);
END luhn;
/
SET SERVEROUTPUT ON
I have this piece of code PL/SQL code in a procedure
for rec in(select t.val, t.cat from table t where a=1)
Loop
v:=(rec.val*rec.cat)/2;
end Loop;
How I can get the sum of all 'v' values?
This will create the sum in another variable, named tempSum
DECLARE
tempSum number (6);
tempSum := 0;
for rec in(select t.val, t.cat from table t where a=1)
Loop
v:=(rec.val*rec.cat)/2;
tempSum := tempSum + V;
end Loop;
Best way:
select sum(t.val * t.cat / 2) into l_val_cat_sum from table t where a = 1;
i was trying to make something like this
when input : 5
it will print
A B C D E
input : 10
print
A B C D E
J I H G F
input : 15
print
A B C D E
J I H G F
K L M N O
input : 20
A B C D E
J I H G F
K L M N O
T S R Q P
and so on...
here is my code i create
declare
angka number := '&Angka';
i number := trunc(angka/5);
p number := 65;
a number := 1;
b number := 1;
begin
while a <= b loop
if mod(i,2) = 1 then
a := 5;
for b in 1..5 loop
p := p + a
dbms_output.put( chr(p) || ' ' );
a := a - 1;
end loop;
p := p + 5;
else
a := 1;
for b in 1..5 loop
p := p + a
dbms_output.put( chr(p) || ' ' );
a := a + 1;
end loop;
end loop;
dbms_output.put_line(' ');
end;
/
but i was still confused it's still didn't work
and about dbms_output.put_line vs dbms_output.put can someone explain this ? because i was trying print using dbms_output.put it's didn't show.. i don't know why
Thanks
Firstly, the line p := p + a has not been terminated by semi-colon. Ideally, the PL/SQL anonymous block shouldn't compile at first place.
Secondly, with PUT procedure, you haven't completed the line yet. It needs GET_LINES to retrieve an array of lines from the buffer.
There was a similar question, Is dbms_output.put() being buffered differently from dbms_output.put_line()?
You have some problems in your code. I don't believe that you can execute exactly this code. Propably, you forgot to copy some parts of it.
First of all, syntax errors:
declare
angka number := '&Angka';
i number := trunc(angka/5);
p number := 65;
a number := 1;
b number := 1;
begin
while a <= b loop
if mod(i,2) = 1 then
a := 5;
for b in 1..5 loop
p := p + a -- ";" missed
dbms_output.put( chr(p) || ' ' );
a := a - 1;
end loop;
p := p + 5;
else
a := 1;
for b in 1..5 loop
p := p + a -- ";" missed
dbms_output.put( chr(p) || ' ' );
a := a + 1;
end loop;
-- here you missed "end if"
end loop;
dbms_output.put_line(' ');
end;
/
Also you don't need your outer loop ("while a <= b loop"), because its condition always is true and code execution will never ends. And last - when you declare
for b in 1..5 loop
oracle creates here new variable with name "b", and inside the loop previously declared b is not visible. Try to execute this:
declare
b number := 111;
begin
for b in 1..5 loop
dbms_output.put_line(b);
end loop;
dbms_output.put_line(b);
end;
/
You will get:
1
2
3
4
5
111
If you correct these errors, your code will work as you want.
An associate of mine converted a javascript inverse chi-square routine to Oracle. The good news is that it returns the same results as the javascript routine. The bad news is that where it takes 1.5 seconds to return the result in IE or Chrome, it takes 23 seconds in Oracle. Of that 23 seconds >99% is CPU time.
There are two loops in the routines, an outer loop that executes 36 times for the values we are testing with, and an inner loop that runs 10,753 times for the each iteration of the outer loop. It does the same loop in both JS as it does in Oracle. For each iteration of the inner loop it executes an EXP function and an LN function, both of which are intrinsic in both languages.
I have compiled the Oracle code both Interpreted as well as Native, with little if any change (.045 second difference).
I have three questions;
Why is Oracle so slow/how can I improve it?
Is there an intrinsic inverse chi square function in Oracle.
Does anyone have an inverse chi-square function that does not require the iterative looping (or not as much) as the one I am using?
A bonus question is;
Does anyone have a routine that computes Confidence Intervals in PL/SQL, or a language that could easily be converted to PL/SQL?
As requested, here is the code, which is a bit long (The main routine is CRITCHI for testing P=0.975 and DF=21507.38);
BIGX Number :=20;
FUNCTION POZ(Z IN NUMBER) RETURN NUMBER IS
Y NUMBER;
X NUMBER;
W NUMBER;
Z_MAX NUMBER;
XXX NUMBER;
BEGIN
Z_MAX:=6.0;
IF (Z=0) THEN
X:= 0.0;
ELSE
Y := 0.5 * ABS(Z);
IF (Y >= (Z_MAX * 0.5)) THEN
X:= 1.0;
ELSIF (y < 1.0) THEN
W:= Y * Y;
X:= ((((((((0.000124818987 * W
- 0.001075204047) * W + 0.005198775019) * W
- 0.019198292004) * W + 0.059054035642) * W
- 0.151968751364) * W + 0.319152932694) * W
- 0.531923007300) * W + 0.797884560593) * Y * 2.0;
ELSE
Y:= Y-2.0;
Y:= (((((((((((((-0.000045255659 * Y
+ 0.000152529290) * Y - 0.000019538132) * Y
- 0.000676904986) * Y + 0.001390604284) * Y
- 0.000794620820) * Y - 0.002034254874) * Y
+ 0.006549791214) * Y - 0.010557625006) * Y
+ 0.011630447319) * Y - 0.009279453341) * Y
+ 0.005353579108) * Y - 0.002141268741) * Y
+ 0.000535310849) * Y + 0.999936657524;
END IF;
END IF;
IF (Z>0.0) THEN
XXX:=((X + 1.0) * 0.5);
ELSE
XXX:= ((1.0 - x) * 0.5);
END IF;
RETURN XXX;
END POZ;
FUNCTION EX(X IN NUMBER) RETURN NUMBER IS
BEGIN
IF (x < -BIGX) THEN
RETURN 0;
ELSE
RETURN EXP(X);
END IF;
END EX;
FUNCTION POCHISQ(X IN NUMBER, DF IN NUMBER) RETURN NUMBER IS
A NUMBER;
Y NUMBER;
S NUMBER;
E NUMBER;
C NUMBER;
Z NUMBER;
X1 NUMBER;
EVEN BOOLEAN; /* True if df is an even number */
LOG_SQRT_PI NUMBER := 0.5723649429247000870717135; /* log(sqrt(pi)) */
I_SQRT_PI NUMBER := 0.5641895835477562869480795; /* 1 / sqrt(pi) */
b1 PLS_INTEGER;
b2 PLS_INTEGER;
e1 PLS_INTEGER;
e2 PLS_INTEGER;
BEGIN
b1 := DBMS_UTILITY.GET_TIME();
b2 := DBMS_UTILITY.GET_CPU_TIME();
X1:=X;
IF (X1 <= 0.0 OR DF < 1) THEN
RETURN 1.0;
END IF;
A:= 0.5 * X1;
EVEN:= (MOD(DF,2)=0);
IF (DF > 1) THEN
Y := ex(-A);
END IF;
IF EVEN THEN
S:=Y;
ELSE
S:=(2.0 * poz(-sqrt(X1)));
END IF;
IF (DF > 2) THEN
X1:= 0.5*(DF-1.0);
IF EVEN THEN
Z:=1.0;
ELSE
Z:=0.5;
END IF;
IF (A > BIGX) THEN
IF EVEN THEN
E:=0.0;
ELSE
E:=LOG_SQRT_PI;
END IF;
C:= LN(A);
/* Timming snippet */
e1 := DBMS_UTILITY.GET_TIME() - b1;
e2 := DBMS_UTILITY.GET_CPU_TIME() - b2;
--DBMS_OUTPUT.PUT_LINE( '0-GET_TIME elapsed = ' || e1 || ' hsecs.' );
--DBMS_OUTPUT.PUT_LINE( '0-GET_CPU_TIME elapsed = ' || e2 || ' hsecs.' );
/* End of Timming snippet */
WHILE (Z <= X1)
LOOP
E:= LN(Z) + E;
S:=S+EX(C * Z - A - E);
Z:=Z+1.0;
END LOOP;
e1 := DBMS_UTILITY.GET_TIME() - b1;
e2 := DBMS_UTILITY.GET_CPU_TIME() - b2;
--DBMS_OUTPUT.PUT_LINE( '1-GET_TIME elapsed = ' || e1 || ' hsecs. Z= ' || Z );
--DBMS_OUTPUT.PUT_LINE( '1-GET_CPU_TIME elapsed = ' || e2 || ' hsecs.' );
RETURN S;
ELSE
IF EVEN THEN
E:=1.0;
ELSE
E:=(I_SQRT_PI / sqrt(A));
END IF;
C:= 0.0;
WHILE (Z <= X1)
LOOP
E:= E * (A / Z);
C:= C + E;
Z:=Z+ 1.0;
END LOOP;
e1 := DBMS_UTILITY.GET_TIME() - b1;
e2 := DBMS_UTILITY.GET_CPU_TIME() - b2;
--DBMS_OUTPUT.PUT_LINE( '2-GET_TIME elapsed = ' || e1 || ' hsecs.' );
--DBMS_OUTPUT.PUT_LINE( '2-GET_CPU_TIME elapsed = ' || e2 || ' hsecs.' );
RETURN C * Y + S;
END IF;
ELSE
e1 := DBMS_UTILITY.GET_TIME() - b1;
e2 := DBMS_UTILITY.GET_CPU_TIME() - b2;
--DBMS_OUTPUT.PUT_LINE( '3-GET_TIME elapsed = ' || e1 || ' hsecs.' );
--DBMS_OUTPUT.PUT_LINE( '3-GET_CPU_TIME elapsed = ' || e2 || ' hsecs.' );
RETURN S;
END IF;
END POCHISQ;
/* CRITCHI -- Compute critical chi-square value to
produce given p. We just do a bisection
search for a value within CHI_EPSILON,
relying on the monotonicity of pochisq(). */
FUNCTION CRITCHI(P IN NUMBER, DF IN NUMBER) RETURN NUMBER IS
CHI_EPSILON NUMBER:= 0.000001; /* Accuracy of critchi approximation */
CHI_MAX NUMBER:= 99999.0; /* Maximum chi-square value */
minchisq NUMBER:= 0.0;
maxchisq NUMBER:= CHI_MAX;
chisqval NUMBER;
dummy_count number := 0;
BEGIN
IF (p <= 0.0) THEN
RETURN maxchisq;
ELSE
IF (p >= 1.0) THEN
RETURN 0.0;
END IF;
END IF;
chisqval:= df / sqrt(p); /* fair first value */
WHILE ((maxchisq - minchisq) > CHI_EPSILON)
LOOP
if (pochisq(chisqval, df) < p) THEN
maxchisq:= chisqval;
ELSE
minchisq:= chisqval;
END IF;
chisqval:= (maxchisq + minchisq) * 0.5;
dummy_count := dummy_count + 1;
END LOOP;
--DBMS_OUTPUT.PUT_LINE('chisqval = ' || chisqval);
RETURN chisqval;
END CRITCHI;
For the benefit of future seekers, who might not have the patience to trawl through all the comments, the following optimizations were applied to the program to make it run fast.
All the numeric variables were declared as BINARY_INTEGER(#). Find out more.
Functions were declared as deterministic.
Functions were compiled into native C.
(#) On more modern versions of the database PLS_INTEGER is preferred (simply because BINARY_INTEGER is old and deprecated - it gets converted to PLS_INTEGER under the covers) .
NB - if the OP or #AlexPoole would care to write a similar response, I'll happily upvote their answer and delete this one.
Before i must say this : Please, excuse me for my bad english...
I'm student.My teacher gave me problem in pascal for my course work...
I must write program that calculates 2^n for big values of n...I've wrote but there is a problem...My program returns 0 for values of n that bigger than 30...My code is below...Please help me:::Thanks beforehand...
function control(a: integer): boolean;
var
b: boolean;
begin
if (a >= 10) then b := true
else b := false;
control := b;
end;
const
n = 200000000;
var
a: array[1..n] of integer;
i, j, c, t, rsayi: longint; k: string;
begin
writeln('2^n');
write('n=');
read(k);
a[1] := 1;
rsayi := 1;
val(k, t, c);
for i := 1 to t do
for j := 1 to t div 2 do
begin
a[j] := a[j] * 2;
end;
for i := 1 to t div 2 do
begin
if control(a[j]) = true then
begin
a[j + 1] := a[j + 1] + (a[j] div 10);
a[j] := a[j] mod 10;
rsayi := rsayi + 1;
end;
end;
for j := rsayi downto 1 do write(a[j]);
end.
The first (nested) loop boils down to "t" multiplications by 2 on every single element of a.
30 multiplications by two is as far as you can go with a 32-bit integer (2^31-1 of positive values, so 2^31 is out of reach)
So the first loop doesn't work, and you probably have to rethink your strategy.
Here is a quick and dirty program to compute all 2^n up to some given, possibly large, n. The program repeatedly doubles the number in array a, which is stored in base 10; with lower digit in a[1]. Notice it's not particularly fast, so it would not be wise to use it for n = 200000000.
program powers;
const
n = 2000; { largest power to compute }
m = 700; { length of array, should be at least log(2)*n }
var
a: array[1 .. m] of integer;
carry, s, p, i, j: integer;
begin
p := 1;
a[1] := 1;
for i := 1 to n do
begin
carry := 0;
for j := 1 to p do
begin
s := 2*a[j] + carry;
if s >= 10 then
begin
carry := 1;
a[j] := s - 10
end
else
begin
carry := 0;
a[j] := s
end
end;
if carry > 0 then
begin
p := p + 1;
a[p] := 1
end;
write(i, ': ');
for j := p downto 1 do
write(a[j]);
writeln
end
end.