Im trying to update values in PL SQL. The problem is that my dbms_output.put_line is working fine, everything is writen good, but execute immediate doesn't work. The funny thing is, that it works once (or even two) but now it doesn't work. I don't know how to resolve this problem.
Program that i write is inserting some random values into table that is created from values that are input veriables. code can be little to long to be throwed here, i put the most important part of code
for looper in 1..y loop
execute immediate 'insert into GAME ' || s_string || ' values '
|| rowGenerator(v_low=>1, v_high=>6, v_x=>x);
end loop;
start_x_point:= round (dbms_random.value( high=>x, low=>1));
start_y_point:= round (dbms_random.value( high=>y, low=>1));
dbms_output.put_line(start_x_point || ' ' || start_y_point);
s_temp:= ' set x' || start_x_point || ' = 0 where ROWNUM = '|| start_y_point;
dbms_output.put_line(s_temp);
execute immediate 'update GAME ' || s_temp;
s_string conteining bracket with columns,
rowGenerator insert random values into table,
start_x_point and start_y_point is the place where i want to put 0 value
and the problem is that it doesn't works. I don't know other way to do that.
that is how my table looks like after puting random values, its a matrix with values
x1 x2 x3 x4 x5 x6 x7 x8
1 2 5 3 2 4 1 1 3
2 2 3 2 5 4 5 3 3
3 4 3 4 2 4 2 6 3
4 2 1 1 4 3 2 4 1
5 1 5 2 5 3 3 5 4
6 1 5 5 1 1 3 5 3
7 5 3 3 4 4 3 1 3
8 5 4 5 6 3 4 3 2
It appears that your problem is ROWNUM = .... It'll work only when START_Y_POINT = 1, and won't work when it is not.
What to do? Don't use ROWNUM; UPDATE values that depend on something else (some ID value, perhaps?).
Thanks to #Littlefoot i got answer!
i just need to put something like that
select * from (select * from game
where rownum <=start_y_point
order by rownum desc)
where rownum=1;
and i getting the row that i want!
Related
I have a table in Oracle that has a column that I would like to assign a value to from a set of possible values. I like to assign the values in order of the set, repeatedly, for the entire table.
For example:
If the set of values is {1, 2, 3}. I'd like to assign the values in this pattern until the last row is reached:
rowNum someCol valueCol
1 this 1
2 is 2
3 some 3
4 other 1
5 column 2
6 in 3
7 the 1
8 table 2
I can't figure out how to do this with a traditional update statement. Anone that could help with this problem?
Use Modulo to achieve desire result
UPDATE TableName
SET valueCol= CASE WHEN rowNum % 3 == 1 then 1
WHEN rowNum % 3 == 2 then 2
WHEN rowNum % 3 == 0 then 3
END
update tablename
set valuecol = case mod(rownum, 3) when 0 then 3 else mod(rownum, 3) end
;
I have been reading about CONNECT BY and CTE in Oracle, but I can't come up with a solution. I don't know how to use properly CONNECT BY to my needs, and recursive CTE's in Oracle are limited to 2 branches(one UNION ALL) and I'm using 3 branches.
In SQL Server it was kind of easy after I found this article. I only added another UNION ALL regarding to return all node references.
What I trying to do is having a hierarchy like this:
Code|Father
1 |NULL
2 |1
3 |2
And this should return me:
Node|Father|Level|JumpsToFather
1 |1 |1 |0
2 |1 |2 |1
2 |2 |2 |0
3 |1 |3 |2
3 |2 |3 |1
3 |3 |3 |0
Note: Yes I need to return a reference to themselves counting as zero jumps on the hierarchy
Here is a solution using a recursive CTE. I used lvl as column header since level is a reserved word in Oracle. You will see other differences in terminology as well. I use "parent" for the immediately higher level and "ancestor" for >= 0 steps (to accommodate your requirement of showing a node as its own ancestor). I used an ORDER BY clause to cause the output to match yours; you may or may not need the rows ordered.
Your question stimulated me to read again, in more detail, about hierarchical queries, to see if this can be done with them instead of recursive CTEs. Actually I already know you can, by using CONNECT_BY_PATH, but using a substr on that just to retrieve the top level in a hierarchical path is not satisfying at all, there must be a better way. (If that was the only way to do it with hierarchical queries, I would definitely go the recursive CTE route if it was available). I will add the hierarchical query solution here, if I can find a good one.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual
),
r ( node , ancestor, steps ) as (
select node , node , 0
from h
union all
select r.node, h.parent, steps + 1
from h join r
on h.node = r.ancestor
)
select node, ancestor,
1+ (max(steps) over (partition by node)) as lvl, steps
from r
where ancestor is not null
order by lvl, steps desc;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
Added: Hierarchical query solution
OK - found it. Please test both solutions to see which performs better; from tests on a different setup, recursive CTE was quite a bit faster than hierarchical query, but that may depend on the specific situation. ALSO: recursive CTE works only in Oracle 11.2 and above; the hierarchical solution works with older versions.
I added a bit more test data to match Anatoliy's.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual union all
select 4 , 2 from dual union all
select 5 , 4 from dual
)
select node,
connect_by_root node as ancestor,
max(level) over (partition by node) as lvl,
level - 1 as steps
from h
connect by parent = prior node
order by node, ancestor;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0
thx for question, i spent 1 hour to write this:
with t as ( select code, parent, level l
from (select 1 as code, NULL as parent from dual union
select 2 , 1 from dual union
select 3 , 2 from dual
-- add some more data for demo case
union
select 4 , 2 from dual union
select 5 , 4 from dual
)
start with parent is null
connect by prior code = parent )
select code, (select code
from t t1
where l = ll
and rownum = 1
start with t1.code = main_t.code
connect by prior t1.parent = t1.code
) parent,
l code_level,
jumps
from (
select distinct t.*, l-level jumps, level ll
from t
connect by level <= l
) main_t
order by code, parent
as you can see, i'am add some more data to test my sql, here is output
CODE PARENT CODE_LEVEL JUMPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0
13 rows selected
I need an o/p as below.
1,1
2,1
2,2
3,1
3,2
3,3
4,1
4,2
4,3
4,4
... and so on.
I tried to write the query as below. But throwing error. SIngle row subquery returns more than one row.
with test1 as(
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <59)
select n,(
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <n) from test1
Appreciate your help in solving the same.
Here is one of the methods how you could get the desired result:
SQL> with t1(col) as(
2 select level
3 from dual
4 connect by level <= 5
5 )
6 select a.col
7 , b.col
8 from t1 a
9 join t1 b
10 on a.col >= b.col
11 ;
COL COL
---------- ----------
1 1
2 1
2 2
3 1
3 2
3 3
4 1
4 2
4 3
4 4
5 1
5 2
5 3
5 4
5 5
15 rows selected
I have a table which has a column call numbers
Numbers
------
3
5
I am trying to get the factorial of those. I am using the below logic but not with proper result
Select
Numbers
,EXP(SUM(LN(Numbers)) OVER (ORDER BY Numbers)) Factorial
FROM testTbl
*Output
*
Numbers Factorial
------ ---------
3 3.00000000000000000000000000000000000001
5 15.0000000000000000000000000000000000002
What is wrong? Please help
Expected
--------
Numbers Factorial
------ ---------
3 6
5 120
Thanks in advance
I've had a go at this from another angle, trying to do it all in a SQL statement (using your table testTbl and the column numbers).
This is what I've come up with, see if it suits you:
SELECT testtbl.numbers,
ROUND( EXP( SUM( LN( t1.n ) ) ) ) AS factorial
FROM ( SELECT UNIQUE LEVEL n
FROM testtbl
CONNECT BY LEVEL <= numbers) t1,
( SELECT UNIQUE LEVEL n
FROM testtbl
CONNECT BY LEVEL <= numbers) t2,
testTbl
WHERE t1.n <= t2.n
AND t2.n = testTbl.numbers
GROUP BY testtbl.numbers
ORDER BY testtbl.numbers;
Gives the output:
Numbers Factorial
3 6
5 120
Hope it helps...
Were it me, I'd create a factorial function and call that user-defined function in my query. Something like
SQL> create function factorial( p_n in number )
2 return number
3 is
4 begin
5 if( p_n = 1 )
6 then
7 return p_n;
8 else
9 return p_n * factorial( p_n - 1 );
10 end if;
11 end;
12 /
Function created.
SQL> with t as (
2 select 3 num from dual
3 union all
4 select 5 from dual
5 )
6 select num,
7 factorial(num)
8 from t;
NUM FACTORIAL(NUM)
---------- --------------
3 6
5 120
If for some reason you cannot define a new function and you really want to do it in SQL, you'll can generate all the numbers less than the number in your table and then aggregate those generated numbers.
SQL> ed
Wrote file afiedt.buf
1 with t as (
2 select 3 num from dual
3 union all
4 select 5 from dual
5 )
6 select t.num,
7 exp( sum(ln(gen.num))) factorial
8 from (select level num
9 from dual
10 connect by level <= (select max(t.num) from t)) gen,
11 t
12 where gen.num <= t.num
13* group by t.num
SQL> /
NUM FACTORIAL
---------- ----------
5 120
3 6
I need to do an incremental sum in Oracle.
My situation is the following:
RecordID Value
1 1
2 2
3 5
4 10
And I need to get something like this:
RecordID Sum_incremental
1 (1)
2 (1 + 2)
3 (1 + 2 + 5)
4 (1 + 2 + 5 + 10)
The clues: self join and group by.
The solution:
select a.recordid, sum(b.value) sum_incremental from mytable a, mytable b
where b.recordid <= a.recordid group by a.recordid
select recordid,
sum(value) over (order by recordid)
from some_data