Informix - update SET column with results from a subselect - sql

I have a table with a collection column. I want to do a subselect which returns several integers and put the result in that collection column, however I can't find a syntax to do it through SQL. I did it by writing an SQL procedure which does the same thing (put results of SELECT in SET variable and return variable), however I'm trying to do the same without functions. Can it be done?
First, I create a temporary table:
CREATE TEMP TABLE table1 (
id INTEGER
, col2 SET(INT NOT NULL)
)
Then I fill it with test data:
INSERT INTO table1 (id) VALUES (1);
INSERT INTO table1 (id) VALUES (2);
And now this works:
UPDATE table1 SET col2 = SET{1,2};
...but I'm trying to do this and it doesn't work:
UPDATE table1 SET col2 = (SELECT id FROM table1) WHERE id = 1;
It returns this error:
[Error Code: -9632, SQL State: IX000] Value does not match the type of column (col2).

Manipulating SET types in pure SQL is a pain.
Your UPDATE is trying to assign an INTEGER to a SET OF INTEGER, and the error says "you can't do that".
You should be able to do:
UPDATE table1
SET col2 = SET { (SELECT id FROM table1 WHERE id = 1) }
WHERE id = 1;
However, I'm not sure what the correct modification is to get more than one value into the set; the inner WHERE is not there idly.

You can achieve this by using MULTISET and ITEM keyword
the following example will work:
CREATE TEMP TABLE table1 (
id INTEGER
,col2 MULTISET(INT NOT NULL)
);
INSERT INTO table1 (id) VALUES (1);
INSERT INTO table1 (id) VALUES (2);
UPDATE table1 SET col2 = MULTISET{1,2};
UPDATE table1
SET col2 = MULTISET(SELECT ITEM id FROM table1)
WHERE id = 1;
Be aware of the differences between SET and MULTISET
select set{1,2,1,3,1} from systables where tabid=1;
returns SET{1,2,3}
select multiset{1,2,1,3,1} from systables where tabid=1;
returns MULTISET{1,2,1,3,1}

Related

Setting Postgresql variable from result of insert for future use

I have a table with a UUID key that is generated on insert. I need to use that key in multiple future inserts and want to store it in a variable.
CREATE TABLE table1 (UUID uuid PRIMARY KEY DEFAULT gen_random_uuid(), blah integer);
CREATE TABLE table2 (UUID uuid PRIMARY KEY DEFAULT gen_random_uuid(), UUID table1Uuid);
INSERT INTO TABLE1 (blah) values (1234);
INSERT INTO TABLE1 (blah) values (6789);
.....
INSERT INTO TABLE2 (table1Uuid theUuidMadeFromInsert1234);
I think I can make sure all the future inserts into TABLE2 are in the same session (maybe the same script) as those for TABLE1. Would like to do something like
uuid1234 = INSERT INTO TABLE1 (blah) values (1234);
uuid6789 = INSERT INTO TABLE1 (blah) values (6789);
.....
INSERT INTO TABLE2 (table1Uuid uuid1234);
but I can't get any syntax to work. I tried
create or replace function insertTable1 (junk integer)
RETURNS UUID
LANGUAGE plpgsql AS
$func$
declare
myUuid UUID;
BEGIN
insert into table1 (blah) values (junk) returning uuid into myUuid;
return myUuid;
END
$func$;
then doing something like set my.var.uuid = select insertTable1(1234) and insert into table2 (table1Uuid my.var.uuid) with various uses of current_setting
I have read many posts on SO, but can't find one that allows the value of the variable to outlast the function and be used
Is this what you want?
with t1 as (
insert into table1 (blah) values (1234), (6789)
returning *
)
insert into table2 (table1Uuid)
select uuid from t1 where blah = 1234;
The CTE inserts several rows in table1, then the outer query inserts in table2 the uuid that was generated for blah 1234.
Note that if you insert 1234 more than once in the CTE, the outer query will create as many rows in table2.
Alernatively, you can isolate the first insert in another CTE:
with
t1 as (insert into table1 (blah) values (1234) returning *),
t2 as (insert into table1 (blah) values (456), (789))
insert into table2 (table1Uuid) select uuid from t1

Generate ID for duplicate values in sql server

I found following link to assign identical ID to duplicates in SQL server,
my understanding there is no sql server function to automatically generate it rather than using insert and update queries in link attached, is that statement True, if yes, then what would be the trigger if for example someone insert data to MyTable then run insert and update query from link:
Assign identical ID to duplicates in SQL server
INSERT INTO secondTable (word) SELECT distinct word FROM MyTable;
UPDATE MyTable SET ID = (SELECT id from secondTable where MyTable.word = secondTable.word)
thanks,
S
Is this what you want? I can't think of an "automatic" solution that would just increase the Id for new words.
CREATE TABLE MyTable (
Id INT NOT NULL,
Word NVARCHAR(255) NOT NULL
PRIMARY KEY (Id, Word)); -- primary key will make it impossible to have more than one combination of word and id
DECLARE #word NVARCHAR(255) = 'Hello!';
-- Get existing id or calculate a new id
DECLARE #Id INT = (SELECT Id FROM MyTable WHERE Word = #word);
IF(#id IS NULL) SET #Id = (SELECT MAX(Id) + 1 FROM MyTable);
INSERT INTO MyTable (Id, Word)
VALUES (#id, #word)
SELECT * FROM MyTable
If you can't for some reason have id and word as a combined primary key, you may use an unique index to make sure that there is only one combination

update each row (sql server) based on subquery

I want to update each row of table1->keyField based on table2 value
Table1
Id|keyField
1|test_500
2|test_501
3|test_501
500,501 are primary key of and my another table2
Table2
Id|value
500|A
501|B
502|C
I have tried something like
update table1 set keyField=(select value from table2 where id=substring(expression))
but my select return multiple statement so unable to run the query.
any help or direction please?
You can use the syntax like this
UPDATE table1 SET keyField = Table2.Value
FROM table1 INNER JOIN table2
ON table1.Id = substring(expression))
If I get it right, this might be what you need:
UPDATE T1 SET
keyField = T2.Value
FROM
Table1 AS T1
INNER JOIN Table2 AS T2 ON T2.id = SUBSTRING(T1.keyField, 6, 100)
Careful when comparing substring result with an numeric value, might get a conversion error.
Try this code (necessary notes are in comments below):
--generate some sample data (the same as you provided)
declare #table1 table (id int, keyField varchar(10))
insert into #table1 values (1,'test_500'),(2,'test_501'),(3,'test_502')
declare #table2 table (id int, value char(1))
insert into #table2 values (500,'A'),(501,'B'),(502,'C')
--in case you want to see tables first
--select * from #table1
--select * from #table2
--here you extract the number in first table in keyField column and match it with ID from second table, upon that, you update first table
update #table1 set keyField = value from #table2 [t2]
where cast(right(keyfield, len(keyfield) - charindex('_',keyfield)) as int) = [t2].id
select * from #table1

How can I use SQL MERGE to insert if not exists, and SET a variable to the Id?

I have an Id column set by SEQUENCE
Given a varchar I need to INSERT if there is not match, and return an Id.
The Id will be either:
The existing Id of the row with the matchine ItemName
The new Id generated by the sequence because a row was inserted
NULL because the string was passed as NULL
I'm trying to MERGE into the table to insert if not exists, otherwise get the Id. I need it to be threadsafe.
Here is what I have so far but I'm thinking there is a better way:
DECLARE #vValueId INT NULL
DECLARE #inserted AS TABLE (Id INT NOT NULL)
MERGE
dbo.foo WITH (HOLDLOCK) AS f
USING
(SELECT #vName AS val WHERE #vName IS NOT NULL) AS new_item
ON f.ItemName = new_item.val
WHEN MATCHED THEN
UPDATE SET #vValueId = f.Id
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ItemName)
VALUES
(#vName)
OUTPUT inserted.Id AS Id INTO #inserted;
SELECT #vValueId = ISNULL(s.Id, #vValueId) FROM #inserted AS s

How to compare column of two table and insert a value into new table based on comparison in stored procedure in SQL Server

I want to create a procedure which should check a column between two tables and insert a value into another table based on comparison.
Table 1:
create table table1
(
ID int not null primary key,
)
Table 2:
Create table table2
(
ItemID int not null primary key,
ID int FOREIGN KEY REFERENCES Orders(OrderID) ,
Descp Text
)
Table 3:
create table table3
(
ID int,
ItemCheck char
)
value of ID column of table 3 should be same as table1's ID column and
if ID column of table1 table exist in table2 then value ItemCheck column of table3 should be 'true' oterwise 'false'.
Please give me some ideas and let me know if you have any doubt. Thanks in advance.
Sounds like you want something like this?
TRUNCATE table3;
INSERT INTO table3 (ID, ItemCheck)
SELECT ID,
CASE WHEN EXISTS (SELECT 1 FROM table2 t2 WHERE ID = t.ID)
THEN 'T'
ELSE 'F'
END
FROM table1 t
Declare #col1 varchar(10)
Declare #col2 varchar(10)
SET #col1 = Select column1 from table1 where id =1
SET #col1 = Select column1 from table1 where id =2
IF(#col1 == #col2)
BEGIN
// insert statement goes here
END