How to use Temporary Tables inside Begin Work - informix

I'm trying to create a script with a set of instructions inside a BEGIN WORK / COMMIT block, but for some reason the temporary table is not being created or is being deleted at some point:
this is the kind of script I'm working on:
-- PHASE2:
BEGIN WORK;
--create a temp table
CREATE temp table IF NOT EXISTS temp_users (
reg_id char(2),
cntry char(2),
name varchar(25)
);
--insert to temp table
INSERT INTO temp_users(reg_id,cntry,name)
SELECT region,country,usr_name FROM user_data WHERE cntry = 'AU';
-- more work with the temp table below..
COMMIT;
But when I execute this script I'm getting an error because temp_users doesn't exists .

I'm not sure what problem you're running into. Using Informix 12.10.FC6 (time to upgrade — and then some) on Ubuntu 18.04, I can run this without error:
DROP TABLE IF EXISTS user_data;
CREATE TABLE user_data
(
region CHAR(2) NOT NULL,
country CHAR(2) NOT NULL,
cntry CHAR(2) NOT NULL,
usr_name VARCHAR(25) NOT NULL
);
-- PHASE2:
BEGIN WORK;
--create a temp table
CREATE TEMP TABLE IF NOT EXISTS temp_users (
reg_id CHAR(2),
cntry CHAR(2),
name VARCHAR(25)
);
--insert to temp table
INSERT INTO temp_users(reg_id, cntry, name)
SELECT region, country, usr_name FROM user_data WHERE cntry = 'AU';
-- more work with the temp table below..
COMMIT;
I don't know why your user_data table has columns country and cntry; that's not obvious.
Try creating a temporary database (a database with a new name that you'll get rid of soon), and then run the script shown against it with DB-Access. It should work, creating a trace like this (I used stores as the database and the file xyz.sql to contain the script):
$ dbaccess stores xyz
Database selected.
Table dropped.
Table created.
Started transaction.
Temporary table created.
0 row(s) inserted.
Data committed.
Database closed.
$
What do you get?

Related

Invalid identifier procedure

I'm writing procedure to transfer data from table in one Db named as 'Dev( or testing)' to another table in fdw db where we'll have repository table. Every month, last business day -2, we'll clean data from dev table and transfer it to repository table.
I'm super new to this technology and testing procedure and getting follwiing error
[Error] ORA-00904 (12: 15):
PL/SQL: ORA-00904: "USB"."BAS2_AGENCY_TO_RISKRATE_REPOS"."AS_OF_DATE: invalid identifier
CREATE OR REPLACE PROCEDURE USB.Basel2_riskrating
AS
BEGIN
INSERT INTO USB.BAS2_AGENCY_TO_RISKRATE_REPOS#OFSADEV --INSERTS DATA IN REPOSITORY TABLE
SELECT *
FROM USB.BAS2_AGENCY_TO_RISKRATING_TRAN M
WHERE USB.BAS2_AGENCY_TO_RISKRATE_REPOS.AS_OF_DATE != M.AS_OF_DATE ; --COMPARES DATE COLUMN TO REMOVE DUPLICACY
COMMIT;
END Basel2_riskrating;
Could you please help me in this. Also, it will be great if one could guide me with sample procedure code in wiping data from USB.BAS2_AGENCY_TO_RISKRATING_TRAN table at each month end.
As suggested in the comments, use NOT EXISTS. It's not celar whether you want to check for duplicates in the remote table usb.bas2_agency_to_riskrate_repos#ofsadev or a local version of the same. Use the appropriate table inside NOT EXISTS to do the comparison.
CREATE OR REPLACE PROCEDURE usb.basel2_riskrating AS
BEGIN
INSERT INTO usb.bas2_agency_to_riskrate_repos#ofsadev
SELECT * FROM usb.bas2_agency_to_riskrating_tran m
WHERE NOT EXISTS ( select 1 from
usb.bas2_agency_to_riskrate_repos e --#ofsadev?
where e.as_of_date = m.as_of_date
);
COMMIT; --Try to avoid commits inside procedure, move it to execution section
END basel2_riskrating;
SELECT * FROM USB.BAS2_AGENCY_TO_RISKRATING_TRAN M WHERE USB.BAS2_AGENCY_TO_RISKRATE_REPOS.AS_OF_DATE != M.AS_OF_DATE ;
is wrong. You can not run such a select against DB, it has no USB.BAS2_AGENCY_TO_RISKRATE_REPOS in from clause

Informix external table pass file name as parameter

I have a stored procedure in Informix that uses external tables to unload data to a disk file from a select statement. Is it possible to give the DISK file name as a parameter to the stored procedure? My stored procedure is as follows:
create procedure spUnloadData(file_name_param varchar(64))
create temp table temp_1(
col_11 smallint
) with no log;
INSERT INTO temp_1 select col1 from data_table;
CREATE EXTERNAL TABLE temp1_ext
SAMEAS temp_1
USING (
--DATAFILES ("DISK:/home/informix/temp.dat")
DATAFILES("DISK:" || file_name_param )
);
INSERT INTO temp1_ext SELECT * FROM temp_1;
DROP TABLE temp1_ext ;
DROP TABLE temp_1;
END PROCEDURE;
I am trying to pass in the DISK filename as a parameter(from my shell script, timestamped).
Any help is appreciated.
NH
You would have to use Dynamic SQL in the stored procedure — for example, the EXECUTE IMMEDIATE statement.
You create a string containing the text of the SQL and then execute it. Adapting your code:
CREATE PROCEDURE spUnloadData(file_name_param VARCHAR(64))
DEFINE stmt VARCHAR(255); -- LVARCHAR might be safer
CREATE TEMP TABLE temp_1(
col_11 SMALLINT
) WITH NO LOG;
INSERT INTO temp_1 select col1 from data_table;
LET stmt = 'CREATE EXTERNAL TABLE temp1_ext ' ||
'SAMEAS temp_1 USING DATAFILES("DISK:' ||
TRIM(file_name_param) ||
'")';
EXECUTE IMMEDIATE stmt;
INSERT INTO temp1_ext SELECT * FROM temp_1;
DROP TABLE temp1_ext;
DROP TABLE temp_1;
END PROCEDURE;
Untested code — the concept should be sound, though.
This assumes you are using a reasonably current version of Informix; the necessary feature is in 12.10, and some version 11.70 versions too, I believe.
I made slight changes to my code to unload data(as Informix default '|' separated fields). Instead of using a temp table, I was able to select columns directly into an external table dynamically.

How to use inner join inside the update query in SQLite in Objective C?

I want to update whole table from on query. Following is my update functionality is happened:
Database (Database A) stored in the iDevice
Temperory Database (Batabase B) downloads to the device and store in the temp folder inside the device. (Both DB has same database structure)
First I attach temp db to device database. Attached db name is SECOND1
Then I insert new records from temp db to device folder from following Insert code. It is working fine.
INSERT INTO main.fList SELECT * FROM SECOND1.fList WHERE not exists (SELECT 1 FROM main.fList WHERE main.fList.GUID = SECOND1.fList.GUID)
But when I use following code to update it is not working fine. It update same top value for all device db table's rows.
UPDATE fList SET Notes = (SELECT SECOND1.fList.Notes FROM SECOND1.fList WHERE SECOND1.fList.GUID = fDefectList.GUID) WHERE EXISTS (SELECT * FROM SECOND1.fList WHERE SECOND1.fList.GUID = fList.GUID
I found SQL query for bulk update. Following is the code,
UPDATE fTempRank7
SET
fTempRank7.int_key = fRank7.int_key,
fTempRank7.int_rank6 = fRank7.int_rank6,
fTempRank7.title = fRank7.title,
fTempRank7.sequence = fRank7.sequence,
fTempRank7.lastupdated = fRank7.lastupdated
FROM
fTempRank7 INNER JOIN fRank7 ON
fTempRank7.int_key = fRank7.int_key
But in sqlite this code does not work.
Anyone knows bulk update in sqlite?
SQLite does not support joins in an UPDATE statement.
When you use a table name without a database name, it refers to the first matching table in the innermost query. In other words, if you use SECOND1.fList in a subquery, any other occurrence of fList refers to the table in SECOND1.
To ensure that you always refer to the correct table, use the database name in all table references.
The main database is always named main, so all table references should be either main.fList or SECOND1.fList.
Anyway, if you are updating all columns, you can simplify the update by deleting the rows that would be updated, so that all new data can just be inserted:
BEGIN;
DELETE FROM fList WHERE GUID IN (SELECT GUID FROM SECOND1.fList);
INSERT INTO fList SELECT * FROM SECOND1.fList;
COMMIT;
When you have a UNIQUE constraint on the GUID column, this can be simplified into a single statement:
INSERT OR REPLACE INTO fList SELECT * FROM SECOND1.fList;
And here I don't use main. because I know what I'm doing. ☺

Informix trigger to change inserted values

I would like to change a couple of column values before they get inserted.
I am using Informix as database.
I have a table consisting of 3 columns: Name (NVARCHAR), Type (INT), Plan (NVARCHAR).
Every time a new record is inserted, I would like to check the Name value before inserting it. If the Name starts with an F, I would like to set the Type value to 1 and the Plan Name to "Test"
In short, what I want the trigger to do is:
For every new insertion, first check if Name value starts with F.
If yes, set the Type and Plan to 1 and "Test" then insert.
If no, insert the values as-is.
I have looked up the CREATE TRIGGER statement with BEFORE and AFTER. However, I would like to have a clearer example. My case would probably involve BEFORE though.
The answer of #user3243781 get close, but did not work because it returns the error:
-747 Table or column matches object referenced in triggering statement.
This error is returned when a triggered SQL statement acts on the
triggering table, or when both statements are updates, and the column
that is updated in the triggered action is the same as the column that
the triggering statement updates.
So the alternative is handle with the NEW variable directly.
For that you need to use a procedure with the triggers reference resource, which means the procedure will able to act like the trigger by self.
Below is my example which I run with dbaccess over a Informix v11.70.
This resource is available only for versions +11 of the engine, as far I remember.
create table teste ( Name NVARCHAR(100), Type INT , Plan NVARCHAR(100) );
Table created.
create procedure check_name_values()
referencing new as n for teste ;;
define check_type integer ;;
define check_plan NVARCHAR ;;
if upper(n.name) like 'F%' then
let n.type = 1;;
let n.plan = "Test";;
end if
end procedure ;
Routine created.
;
create trigger trg_tablename_ins
insert on teste
referencing new as new
for each row
(
execute procedure check_name_values() with trigger references
);
Trigger created.
insert into teste values ('cesar',99,'myplan');
1 row(s) inserted.
insert into teste (name) values ('fernando');
1 row(s) inserted.
insert into teste values ('Fernando',100,'your plan');
1 row(s) inserted.
select * from teste ;
name cesar
type 99
plan myplan
name fernando
type 1
plan Test
name Fernando
type 1
plan Test
3 row(s) retrieved.
drop table if exists teste;
Table dropped.
drop procedure if exists check_name_values;
Routine dropped.
create trigger trg_tablename_ins
insert on tablename
referencing new as new
for each row
(
execute procedure check_name_values
(
new.name,
new.type,
new.plan
)
);
create procedure check_name_values
(
name NVARCHAR,
new_type integer,
new_plan NVARCHAR,
)
define check_type integer ;
define check_plan NVARCHAR ;
let check_type = 1;
let check_plan = "Test";
if name = 'F%'
then
insert into tablename (name,type,plan) values (name,check_type,check_plan);
else
insert into tablename (name,type,plan) values (name,new_type,new_plan);
end if ;
end procedure ;
Here is my version an adaptation of an old example I found in the informix usenet group.
It is possible to update columns in a trigger statement but not very straight forward. You have to use stored procedures an the into statement with the execute procedure command.
It worked here for IBM Informix Dynamic Server Version 12.10.FC11WE.
drop table if exists my_table;
drop sequence if exists my_table_seq;
create table my_table (
id INTEGER
NOT NULL,
col_a char(32)
NOT NULL,
col_b char(20)
NOT NULL,
hinweis char(64),
uslu char(12)
DEFAULT USER
NOT NULL,
dtlu DATETIME YEAR TO SECOND
DEFAULT CURRENT YEAR TO SECOND
NOT NULL
)
;
create sequence my_table_seq
increment 1
start 1;
drop procedure if exists get_user_datetime();
create function get_user_datetime() returning char(12),datetime year to second;
return user, current year to second;
end function
;
drop trigger if exists ti_my_table;
create trigger ti_my_table insert on my_table referencing new as n for each row (
execute function get_user_datetime() into uslu, dtlu
)
;
drop trigger if exists tu_my_table;
create trigger tu_my_table update on my_table referencing new as n for each row (
execute function get_user_datetime() into uslu, dtlu
)
;
insert into my_table values (my_table_seq.nextval, "a", "b", null, "witz", mdy(1,1,1900)) ;
SELECT *
FROM my_table
WHERE 1=1
;

DROP Syntax error in SQLiteManager

I have downloaded sqlite manager app in Firefox browser and open sqlite manager app.
1) Created database named DBSQLTEST.
2) Created table named SQLTEST contain has threes fields are SLNO, NAME and AGE
3) Inserted new records
But i want remove a ‘AGE’ column in sqltest table
i using sql command like below
ALTER TABLE SQLTEST DROP COLUMN AGE
SQLiteManager message says
SQLiteManager: Likely SQL syntax error: ALTER TABLE SQLTEST DROP COLUMN AGE [ near "DROP": syntax error ]
Exception Name: NS_ERROR_FAILURE
Exception Message: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [mozIStorageConnection.createStatement]
What is error that?
sqlite does not support DROP COLUMN in ALTER TABLE. You can only rename tables and add columns.
Reference: http://www.sqlite.org/lang_altertable.html
If you need to remove columns, create a new table, copy the data there, drop the old table and rename the table to its intented name.
SQLite does not fully support ALTER TABLE statements. You can only rename table, or add columns.
If you want to drop a column, your best option is to create a new table without the column, and to drop the old table in order to rename the new one.
For example, suppose you have a table named "t1" with columns names "a", "b", and "c" and that you want to delete column "c" from this table. The following steps illustrate how this could be done:
BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
Credits to Benoit.
Create a table
CREATE TABLE SQLTEST ("SLNO" INTEGER PRIMARY KEY ,"NAME" TEXT,AGE INTEGER)
If want to remove a column
ALTER TABLE SQLTEST RENAME TO SQLTESTCOPY
CREATE TABLE SQLTEST ("SLNO" INTEGER PRIMARY KEY ,"NAME" TEXT)
INSERT INTO SQLTEST"SELECT "SLNO","NAME" FROM SQLTESTCOPY
DROP TABLE SQLTESTCOPY
easy.

Resources