I would like to assign null to a field in SQLite but am not getting anywhere with this:
update t set n=null where n=0;
I can not reproduce your problem. From what you write, I guess your table looks like this:
CREATE TABLE t (n integer);
Inserting data:
insert into t values (1);
insert into t values (2);
insert into t values (3);
insert into t values (0);
Updating the data with your UPDATE:
update t set n = null where n = 0;
Now the table looks like this:
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t (n integer);
INSERT INTO "t" VALUES(1);
INSERT INTO "t" VALUES(2);
INSERT INTO "t" VALUES(3);
INSERT INTO "t" VALUES(NULL);
COMMIT;
There might be no output after the UPDATE but it has the desired effect.
Related
Im trying to create a process that masks data. When I create the trigger I'm getting the error.
ORA-04072: invalid trigger type
I'm unsure why and was hoping someone can explain what the problem is and how to fix it.
The end result is when a user queries cards they should see the masked data and WHEN they query CARDS_TBL they should see all the data (unmasked)
Original implementation
CREATE TABLE CARDS (
CARD_ID NUMBER
GENERATED BY DEFAULT AS IDENTITY,
CARD_STR VARCHAR2(16) NOT NULL,
PRIMARY KEY (CARD_ID)
);
INSERT INTO CARDS(CARD_STR) VALUES('4024007187788590');
INSERT INTO CARDS(CARD_STR) VALUES('5432223398564536');
INSERT INTO CARDS(CARD_STR) VALUES('5430445512530934');
INSERT INTO CARDS(CARD_STR) VALUES('4020156755227854');
INSERT INTO CARDS(CARD_STR) VALUES('5431248766892318');
CREATE OR REPLACE VIEW CARDS_V AS
SELECT
CARD_ID,
REGEXP_REPLACE(CARD_STR, '(^\d{3})(.*)(\d{4}$)', '\1**********\3') AS CARD_STR
FROM CARDS;
CREATE OR REPLACE TRIGGER CARDS_TRG_INSERT INSTEAD OF
INSERT ON CARDS_V
FOR EACH ROW
BEGIN
INSERT INTO CARDS (CARD_STR) VALUES (:NEW.CARD_STR);
END;
INSERT INTO CARDS_V (CARD_STR) VALUES ('4011589733550908');
CREATE OR REPLACE TRIGGER CARDS_TRG_UPDATE INSTEAD OF
UPDATE ON CARDS_V
FOR EACH ROW
BEGIN
UPDATE CARDS
SET CARD_STR = :NEW.CARD_STR
WHERE CARD_ID = :OLD.CARD_ID;
END;
CREATE TABLE CARDS_TBL (
CARD_ID NUMBER
GENERATED BY DEFAULT AS IDENTITY,
CARD_STR VARCHAR2(16) NOT NULL,
PRIMARY KEY (CARD_ID)
);
INSERT INTO CARDS_TBL(CARD_STR) VALUES('4024007187788590');
INSERT INTO CARDS_TBL(CARD_STR) VALUES('5432223398564536');
INSERT INTO CARDS_TBL(CARD_STR) VALUES('5430445512530934');
INSERT INTO CARDS_TBL(CARD_STR) VALUES('4020156755227854');
INSERT INTO CARDS_TBL(CARD_STR) VALUES('5431248766892318');
CREATE OR REPLACE VIEW CARDS AS
SELECT
CARD_ID,
REGEXP_REPLACE(CARD_STR, '(^\d{3})(.*)(\d{4}$)', '\1**********\3') AS CARD_STR
FROM CARDS_TBL;
CREATE OR REPLACE TRIGGER CARDS_TBL_TRG_UPDATE BEFORE UPDATE ON CARDS_TBL
FOR EACH ROW
BEGIN
UPDATE CARDS_TBL
SET CARD_STR = :NEW.CARD_STR
WHERE CARD_ID = :OLD.CARD_ID;
END;
/
CREATE OR REPLACE TRIGGER CARDS_TBL_TRG_INSERT BEFORE INSERT ON CARDS
FOR EACH ROW
BEGIN
INSERT INTO CARDS_TBL (CARD_STR) VALUES (:NEW.CARD_STR);
END;
INSERT INTO CARDS_TBL (CARD_STR) VALUES ('2222333344445555');
SELECT * FROM CARDS_TBL;
UPDATE CARDS_TBL
SET CARD_STR = '2222333344445566'
WHERE CARD_ID = 6;
/
SELECT * FROM CARDS;
In this particular example, at least, the trigger CARDS_TBL_TRG_UPDATE doesn't do anything (except raise a MUTATING TABLE exception) and can be dispensed with. Get rid of it and your example runs as expected. See this db<>fiddle
I have exported a table from one database using Oracle SQL Developer as .sql file and want to import it into another database that has exactly the same table, but the problem is that some entries appear in both tables.
Is there a way when importing using Oracle SQL Developer to exclude entries that already exist in the destination table?
There are at least two ways:
You can use the SQLLDR tool or external table to load
You can load your sql file into the database and then remove duplicates.
Let's use this file:
data.sql
insert into test_table (id) values (1);
insert into test_table (id) values (1);
insert into test_table (id) values (2);
insert into test_table (id) values (2);
insert into test_table (id) values (2);
insert into test_table (id) values (3);
insert into test_table (id) values (3);
SQLLDR:
At first you create integrity constraints for your table for example:
SQL> create table test_table (
2 id number(10) primary key
3 );
Table created.
Then create a control file:
LOAD DATA
INFILE data.sql
INTO TABLE test_table
(
id position(37:37)
)
After running you will see:
SQL> select * from test_table;
ID
----------
1
2
3
And the bad file (This lines were rejected because of the integrity violation):
data.bad
insert into test_table (id) values (1);
insert into test_table (id) values (2);
insert into test_table (id) values (2);
insert into test_table (id) values (3);
You can generate the external table using this control file, so I don't show you how to use it.
Load and remove duplicates:
Let's recreate the test_table table:
SQL> create table test_table (
2 id number(10)
3 );
Table created.
Using SQL Developer load your sql file and check the content:
SQL> select * from test_table;
ID
----------
1
1
2
2
2
3
3
7 rows selected.
and then remove duplicates:
SQL> delete test_table where rowid not in (select min(rowid) from test_table group by id);
4 rows deleted.
SQL> select * from test_table;
ID
----------
1
2
3
I believe there is a way more ways to complete your tasks, I showed only ways that came in my head right away.
I have 2 tables, which were created by executing the following (keep in mind that every query is executed through on node.js, i.e., connection.execute('select....') ):
create table User(userid int not null, name varchar(50) not null, primary key(userid));
create table Random(userid int not null, random int, primary key (userid), foreign key (userid) references User(userid) );
I also added a sequence to auto increment the userid:
create sequence userid_seq;
create or replace trigger userid_bir
before insert on User
for each row
begin
select userid_seq.nextval
into :new.userid
from dual;
end;
/
Now, I have a process whereby after I insert a new user, that user's id is inserted immediately into Random. I browsed through Stackoverflow and came up with:
insert into User(name) values('John');
SET #last_id = LAST_INSERT_ID();
insert into Random(userid, random) values( last_id, 2);
However, I got the following error:
SP2-0735: unknown SET option beginning "#last_id"
Any ideas?
My other concern is that if there are 2 computers trying to insert 2 users (in total) at the same time, the last_id value (or MAX userid value) might mess up. That is, the server might be executing:
insert into User(name) values('John'); ## from Person A
insert into User(name) values('Brian'); ## from Person B
SET #last_id = LAST_INSERT_ID(); ## from Person A, say it's set to 1
SET #last_id = LAST_INSERT_ID(); ## from Person B, say it's set to 2
insert into Random(userid, random) values( last_id, 2); ## from Person A
insert into Random(userid, random) values( last_id, 2); ## from Person B, error: duplicate values?
That's probably MySQL syntax. In Oracle you can use RETURNING INTO clause.
declare
last_id number;
begin
insert into user(name) values('Abcd')
returning userid into last_id;
insert into Random(userid, random) values( last_id, 2);
commit;
end;
/
userid_seq.currval will return the most recent value returned for the sequence in the current session. So you can
INSERT INTO random( userid, random )
VALUES( user_id_seq.currval, 2 );
If you want to have the value in a local variable
DECLARE
l_userid user.user_id%type;
BEGIN
INSERT INTO user(name)
VALUES( 'John' )
RETURNING userid
INTO l_userid;
INSERT INTO random( userid, random )
VALUES( l_userid, 2 );
END;
Example:
IF OBJECT_ID('T1') IS NOT NULL
DROP TABLE T1;
GO
CREATE TABLE T1 (id int PRIMARY KEY, timestamp);
GO
INSERT INTO T1(id) VALUES (1);
GO
declare #v timestamp;
INSERT INTO T1(id) OUTPUT inserted.timestamp as v VALUES (10);
select #v
How can I get the inserted.timestamp into variable #v?
This is what I got to work:
IF OBJECT_ID('T1') IS NOT NULL
DROP TABLE T1;
GO
CREATE TABLE T1 (id int PRIMARY KEY, timestamp);
GO
INSERT INTO T1(id) VALUES (1);
GO
declare #v as table ([timestamp] varbinary) --timestamp;
INSERT INTO T1(id)
OUTPUT inserted.[timestamp] into #v
VALUES (10);
select * from #v
One thing you need to realize is a timestamp field cannot be manually populated. So you must use some other type in your output table. ANd BTW timestamp is deprecated, I would not use it in new development at all. Use rowversion instead. And timestamp doesn't mean it will be a date for those who think it should be like the ANSII Standard, IN SQL Server it is not a date or convertable to a date.
One way would be to use identity:
declare #v timestamp;
declare #ID int;
INSERT INTO T1(id) OUTPUT inserted.timestamp as v VALUES (10);
select #ID =##IDENTITY;
select #v=timestamp from T1 where id=#ID;
(edit)... of course that would require an identity column. Since you know the value of the ID you are inserting then you don't even need to do this, just select the same row after you insert it using your original value.
Is the point you would like to do this all in a single statement? You could probably do it with a trigger but seems unnecessary.
Well, you're inserting a specific value into the ID column, which is the primary key - so just read out the row once you've inserted it...
INSERT INTO T1(id) VALUES (1);
GO
DECLARE #v timestamp
SELECT #v = TIMESTAMP
FROM dbo.T1
WHERE ID = 1
SELECT #v
I'm an MSSQL guy, but I'm working on a DB2 query that needs to create a temp table, insert into it, and do stuff with it. As a much-shortened test, I'm using the following query, which is providing the same result..
declare global temporary table tt_testingSyntax (id int);
insert into session.tt_testingSyntax (id) values (1);
insert into session.tt_testingSyntax (id) values (2);
insert into session.tt_testingSyntax (id) values (3);
insert into session.tt_testingSyntax (id) values (4);
select * from session.tt_testingSyntax;
Zero rows are returned. Why would that be? I've created the tablespace and verified the table is in scope throughout the query.
Try:
declare global temporary table tt_testingSyntax (id int)
ON COMMIT PRESERVE ROWS NOT LOGGED;
insert into session.tt_testingSyntax (id) values (1);
insert into session.tt_testingSyntax (id) values (2);
insert into session.tt_testingSyntax (id) values (3);
insert into session.tt_testingSyntax (id) values (4);
select * from session.tt_testingSyntax;
There are two options...ON COMMIT DELETE ROWS (the default) or ON COMMIT PRESERVE ROWS.
I ended up unknowingly having access to create my own tables (i.e. for user X, I could create X.temp1). Since this query need only be run once, this works fine. Thanks.