Apache Ignite querying _val and _ver columns via sqline - ignite

I am just starting with Apache Ignite and getting errors querying _val and _ver columns.
Using latest docker image:
docker run -it -e "CONFIG_URI=https://raw.githubusercontent.com/apache/ignite/master/examples/config/example-cache.xml" apacheignite/ignite:2.13.0
then from sqlline in container create a simple table with 3 rows:
CREATE TABLE dept
(
deptno LONG,
dname VARCHAR,
loc VARCHAR,
CONSTRAINT pk_dept PRIMARY KEY (deptno)
);
insert into dept (deptno, dname, loc) values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc) values(20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc) values(30, 'SALES', 'CHICAGO');
Now the example I'm following tells me this should work:
Select _key, _val, _ver from dept;
However I am getting errors. From SYS.TABLE_COLUMNS it looks like _ver columns doesn't exist. I see it in prior versions (ex 2.7.0). was it removed?
I can see _val using CAST:
0: jdbc:ignite:thin://127.0.0.1/> SELECT _key, CAST(_val AS VARCHAR) FROM dept;
+------+---------------------------------------------------------------------------------------------------------------------------+
| _KEY | CAST(_VAL AS VARCHAR) |
+------+---------------------------------------------------------------------------------------------------------------------------+
| 10 | SQL_PUBLIC_DEPT_d6d3fe8f_dbf7_4c2a_9c86_3187dc92887c [idHash=1589491372, hash=-850331171, DNAME=ACCOUNTING, LOC=NEW YORK] |
| 20 | SQL_PUBLIC_DEPT_d6d3fe8f_dbf7_4c2a_9c86_3187dc92887c [idHash=2036917729, hash=-1365635177, DNAME=RESEARCH, LOC=DALLAS] |
| 30 | SQL_PUBLIC_DEPT_d6d3fe8f_dbf7_4c2a_9c86_3187dc92887c [idHash=1046181438, hash=1109822257, DNAME=SALES, LOC=CHICAGO] |
+------+---------------------------------------------------------------------------------------------------------------------------+
but not without it
0: jdbc:ignite:thin://127.0.0.1/> SELECT _key, _val FROM dept;
Error: Statement is closed. (state=,code=0)
Has it worked without cast in much older versions, but not anymore?

I don't recall _ver ever existing. What's your example and how old is it?
The use of _key and _val makes sense, though. Your key is a long, which is a sensible SQL value. On the other hand, your value is a collection of two fields. There is no standard SQL type for "collection of two fields" so it fails.
(If you run the same SQL using an Ignite client node, it will work.)

Related

SQL Developer : Export of the query result don't keep the data_type

I am working on a project where I can't connect directly to the database. I wrote a query that get all the data that I need so I can export them. The result of this SQL query have the great data_type but When I export the result, I choose the insert format and at this point all the data_type are switching to string.
Example of the exported data where the number are in the string format wherease in the original database and in the respons of the query, the type is respected :
Insert into MY_TABLE (POSTCODE, NUMBER, ADRESS, CODE, CITY, VALUE) values ('90000', '303', 'HultonLane', '2845', 'BOLTON', '3');
Do you know if there is any way to export the data with the same data_type from the original DB?
Thank for your help, if you need more information I will provide them.
That behavior (or bug?) exists in e.g. SQL Developer version 19.4, but is fixed in 20.2 so - if you're on a lower version, I suggest you upgrade.
Here's an example, based on Scott's DEPT table where DEPTNO column's datatype is NUMBER. Result - when this:
desc dept;
select /*insert*/ * from dept;
is ran as a script - is:
Name Null? Type
------ -------- ------------
DEPTNO NOT NULL NUMBER
DNAME VARCHAR2(20)
LOC VARCHAR2(20)
REM INSERTING into DEPT
SET DEFINE OFF;
Insert into DEPT (DEPTNO,DNAME,LOC) values (10,'ACCOUNTING','NEW YORK');
Insert into DEPT (DEPTNO,DNAME,LOC) values (20,'RESEARCH','DALLAS');
Insert into DEPT (DEPTNO,DNAME,LOC) values (30,'SALES','CHICAGO');
Insert into DEPT (DEPTNO,DNAME,LOC) values (40,'OPERATIONS','BOSTON');
As you can see, all DEPTNO values are numbers. In 19.4, you'd have e.g.
Insert into DEPT (DEPTNO,DNAME,LOC) values ('10','ACCOUNTING','NEW YORK');
('10', a string).
You don't have to do anything about it; the result is the same regardless you run such a select statement, or right-click table name and "Export" data as insert statements.
BTW, our versions match: Mine is 20.2.0.175, build 175.1842.

there is few mistake in trigger help me to solve that problem

Create trigger that will
not allow update of salary for employee
who are in sales department.
Emp(no,name,dno,salary,designamtion)
Dept(dno,name,location)
Errors: TRIGGER MYTRIGGER1
Line/Col: 6/11 PLS-00049: bad bind variable 'OLD.EMP'
Line/Col: 6/31 PLS-00049: bad bind variable 'OLD.EMP'
DROP TABLE EMP;
DROP TABLE DEPT;
CREATE TABLE Dept
(
dno NUMBER PRIMARY KEY,
name VARCHAR(15),
location VARCHAR(15) );
CREATE TABLE Emp
(
no NUMBER PRIMARY KEY,
name VARCHAR(15),
dno NUMBER,
salary NUMBER,
designamtion VARCHAR(15),
FOREIGN KEY(dno) REFERENCES Dept(dno) );
insert into DEPT values (1,'SALES','GUJARAT');
insert into DEPT values (2,'MARKETING','UP');
insert into DEPT values (3,'MANUFACTURING','MP');
insert into DEPT values (4,'DEALING','VAPI');
insert into DEPT values (5,'SELL','TAPI');
insert into EMP values (1,'AMAN',2,45400,'MANAGER');
insert into EMP values (2,'BHAMAN',5,20000,'GM');
insert into EMP values (3,'CHAMAN',3,34400,'ADVISOR');
insert into EMP values (4,'DAMAN',4,75400,'WORKER');
insert into EMP values (5,'KHAMAN',1,42400,'MANAGER');
CREATE OR REPLACE trigger MYTRIGGER1
BEFORE UPDATE OF SALARY ON EMP
for each row
declare
hmmm VARCHAR(15);
begin
select Dept.name into hmmm
from Dept, Emp
where :old.emp.no=no and :old.emp.dno=Dept.dno;
dbms_output.put_line(hmmm);
end;
You don't need to alias the table the trigger is on. This will compile fine:
CREATE OR REPLACE trigger MYTRIGGER1
BEFORE UPDATE OF SALARY ON EMP
for each row
declare
hmmm VARCHAR(15);
begin
select Dept.name into hmmm
from Dept, Emp
where :old.no=no and :old.dno=Dept.dno;
dbms_output.put_line(hmmm);
end;
However, this trigger will fail when you update the table. You cannot select from the table itself in the trigger body. This will raise a mutating table error. Since it is an assignment I'll leave the research up to you.
As Koen said, your code will suffer from mutating table error.
Lucky you - you don't have to select from the table you're just updating (the emp table, right?) - you have everything you need in :new.dno. So:
SQL> create or replace trigger mytrigger1
2 before update of salary on emp
3 for each row
4 declare
5 hmmm varchar2(15);
6 begin
7 select d.name
8 into hmmm
9 from dept d
10 where d.dno = :new.dno;
11
12 dbms_output.put_line('Department name = ' || hmmm);
13 end;
14 /
Trigger created.
Testing:
SQL> set serveroutput on
SQL>
SQL> update emp set salary = 1000 where no = 1;
Department name = MARKETING
1 row updated.
SQL> update emp set salary = 1000;
Department name = MARKETING
Department name = SELL
Department name = MANUFACTURING
Department name = DEALING
Department name = SALES
5 rows updated.
SQL>
Your request is a trigger that disallows certain action for employees in Sales. Your trigger would not do so even it compiled. Two problems:
dbms_output does not prevent anything it merely 'prints' a message.
it prevents any update to salary, except when emp.dno or emp.no is also updated.
First (getting up on soapbox). You are enforcing a business rule. This should not be done in a trigger. It should be done in either the business rules engine of your application or in a database constraint or if you want to be super cautions both. Now a trigger will do the enforcement but business rule violations should glaringly obvious and easy to find, in a trigger becomes a side effect of an action, hidden away and difficult to find. (OK enough of that getting off soapbox).
The prevention method your looking for is raise_application_error. And you want a little code as possible in a trigger. In this case you have everything needed from the EMP table through the pesudo rows :old and :new so there is no reason to join your tables. However you do need to look at the specific department. It is too bad Oracle constrains the Exists predicate to introduction of a sub-select, this would be a perfect place for the structure:
If EXISTS (selects ...) then ...
But that is not available. The following uses a technique of reversing the requirement. That is it selects what is NOT wanted then if found it raise the exception, and if not found it suppress the Oracle raised error. So:
create or replace trigger mytrigger1
before update of salary on emp
for each row
declare
hmmm varchar2(01);
begin
select null
into hmmm
from dept d
where d.dno = :old.dno
and d.name = 'SALES';
raise_application_error(-20199, 'Can not update salary for Employee in Sales.');
exception
when no_data_found then null;
end mytrigger1;
This is sometimes referred to as "Programming the Exception" and is not a generally recommended procedure but at times it is useful. See fiddle here.
There is an outstanding question not addressed here. Can an employee in Sales have a salary change if they are also transferring departments. I.e. should the following succeed or fail?
update emp e
set dno = 2
, salary = salary + 5000
where e.no = 5;

How to format currency in Oracle SQL Developer 19.4.0?

I'm using SQL developer in one of my database classes and I have homework where certain formatting is needed. When I use the commands given by the professor on my SQL Developer I get an error
Here are the commands:
col price format $99,990.99
col quoted_price format $99,990.99
col balance format $99,990.99
col credit_limit format 99,990.99
The errors I get are:
SP2-0246: Illegal FORMAT string "$99,"
SP2-0246: Illegal FORMAT string "$99,"
SP2-0246: Illegal FORMAT string "$99,"
SP2-0246: Illegal FORMAT string "99,"
When I run these same commands on the lab computer it works but the lab uses an outdated version of SQL developer. It's version 4.1.1
Would appreciate any help
The homework is asks us to input a command that would display query results for example a question would be "x" situation
My command will be:
SELECT item_num, price, description, balance
from item;
The query output below will have $ if needed and will have the commas and periods.
If you are storing salary as Number, then you can use to_char(column,'$9,999.99');
SQL> CREATE TABLE EMP
2 (EMPNO NUMBER(4) NOT NULL,
3 ENAME VARCHAR2(10),
4 JOB VARCHAR2(9),
5 MGR NUMBER(4),
6 HIREDATE DATE,
7 SAL NUMBER(7, 2),
8 COMM NUMBER(7, 2),
9 DEPTNO NUMBER(2)
10 );
SQL> INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902,TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
SQL> select ename, to_char( sal, '$9,999.99' ) "Salary" from emp;
ENAME Salary
---------- ----------
SMITH $800.00

Is it possible to duplicate all values in a table while updating one or more columns

I have a table with many columns, and what I would like to do is duplicate all of the rows in the table, but also update one of the columns to a new value.
For example lets say I have the table below. I want to add to my table a duplicate of each row, except instead of BASIC access, it will have 'ADVANCED':
Before:
NAME, GENDER, ACCESS
----------------------
STEVE, MALE, BASIC
MOLLY, FEMALE, BASIC
After
NAME, GENDER, ACCESS
----------------------
STEVE, MALE, BASIC
MOLLY, FEMALE, BASIC
STEVE, MALE, ADVANCED
MOLLY, FEMALE, ADVANCED
Is there a way to do this without specifying all columns? I have 60 columns in the table, and the structure can change (meaning columns may be added, removed, renamed, etc).
Is it possible in Oracle SQL to automate this?
Just use insert . . . select:
insert into t (name, gender, access)
select name, gender, 'ADVANCED'
from t;
You need to list all the columns. You can shorten the manual process by using a query to generate the list. If you had to do this a lot and always knew you were leaving out access and access is the last column, you could use a view:
create view v_t as
select . . . -- all but access
from t;
insert into t ( . . . )
select v.*, 'ADVANCED'
from v_t;
Or you could use dynamic SQL to generate the statement.
However, I don't recommend any of those. Instead I would be concerned about a data model where you are regularly adding and modifying the columns in a table. That sounds dangerous.
Without specifying all the columns? With some help of a "temporary" table, here's how:
Your current table:
SQL> create table test
2 (name varchar2(10),
3 gender varchar2(20),
4 caccess varchar2(20));
Table created.
SQL> insert into test
2 select 'steve', 'male', 'basic' from dual union all
3 select 'molly', 'female', 'basic' from dual;
2 rows created.
Create a "temporary" table as a copy of the "original" table
update column you want to modify
copy the whole "temporary" table to the "original"
drop the "temporary" table
SQL> create table test_temp as select * From test;
Table created.
SQL> update test_temp set caccess = 'advanced';
2 rows updated.
SQL> insert into test select * From test_temp;
2 rows created.
SQL> drop table test_Temp;
Table dropped.
SQL> select * From test;
NAME GENDER CACCESS
---------- -------------------- --------------------
steve male basic
molly female basic
steve male advanced
molly female advanced
SQL>
Apparently, that works, but - what if the original table is huge? It takes a lot of space, and its copy takes approximately twice as much. Why are you doing that, anyway?
Try below method with anonymous block to avoid listing columns in insert statements
CREATE TABLE ACCESS_CHN
(NAAME VARCHAR2(100),
GENDER VARCHAR2(20),
ACCCESS VARCHAR2(30))
INSERT into ACCESS_CHN values('STEVE','MALE','BASIC');
INSERT into ACCESS_CHN values('MOLLY','FEMALE','BASIC');
COMMIT;
DECLARE
column_list varchar2(2000):=NULL;
plsql_block VARCHAR2(1000);
BEGIN
select LISTAGG(column_name,',') within group (order by column_id)
into column_list
from user_tab_columns
where table_name='ACCESS_CHN';
plsql_block := 'CREATE TABLE ACCESS_CHN_BKP as select '|| column_list || ' from ACCESS_CHN';
EXECUTE IMMEDIATE plsql_block;
plsql_block := 'UPDATE ACCESS_CHN_BKP set ACCCESS=''ADVANCED'' ';
EXECUTE IMMEDIATE plsql_block;
COMMIT;
plsql_block := 'CREATE TABLE ACCESS_CHN_FINAL as select * from ACCESS_CHN
union all
select * from ACCESS_CHN_BKP';
EXECUTE IMMEDIATE plsql_block;
END;
--To rerun drop tables ACCESS_CHN_BKP and ACCESS_CHN_FINAL

Migrate Existing Data Into VARRAY Types

I have the following VARRAY type defined in my db schema:
create or replace type STRING_VECTOR is varray(10) of varchar2(50);
I also have the following Employee database table
first name| last name| salary
'John' | 'Doe' | 10.00
Note that the salary column is a NUMBER(38,14).
What I would like to do is add a fourth column that is of my STRING_VECTOR type. I would like to populate my string vector with String values for each record like so:
first name| last name| salary| data
'John' | 'Doe' | 10.00 | ['John', 'Doe', '10.00']
Could someone give me some pointers as to whether PL/SQL can be written to achieve this?
This is not hard at all, take a look:
CREATE TABLE my_emp_test (
first_name VARCHAR2(20),
last_name VARCHAR2(20),
salary NUMBER(38, 14)
);
INSERT INTO my_emp_test VALUES ('John', 'Doe', 10.00);
COMMIT;
CREATE OR REPLACE TYPE string_vector IS VARRAY(10) OF VARCHAR2(50);
ALTER TABLE my_emp_test ADD data string_vector;
UPDATE my_emp_test
SET data = string_vector(first_name, last_name, TO_CHAR(salary))
;
COMMIT;
SELECT * FROM my_emp_test;
FIRST_NAME LAST_NAME SALARY DATA
-------------------- -------------------- ---------- ------------------------------------
John Doe 10 HR.STRING_VECTOR('John','Doe','10')
You wrote that you wanted PL/SQL, but it can be done in pure SQL as you can see, is that going to work for you?