SQL - Dynamic Lookup with Regex - sql

I would like to determine the ownership of a folder. Therefore every folder has a constant naming convention, which is stored in the table OWNER(ident_string).
Using the ident_string I want to determine the owner_id and write it (update) into table FOLDER(owner_id).
I have following tables in Postgresql:
create table owner(
owner_id serial PRIMARY KEY,
owner_name varchar(100),
ident_string varchar(100));
create table folder(
folder_id serial PRIMARY KEY,
folder_name varchar(80),
folder_path varchar(800),
owner_id integer references owner(owner_id));
insert into owner (owner_name, ident_string) values ('Jonny English','b-jonny');
insert into owner (owner_name, ident_string) values ('Hanna Babara','b-hanna');
insert into owner (owner_name, ident_string) values ('Mary Marmelade','b-mary');
insert into folder (folder_name,folder_path) values ('b-jonny-20130101','/archive/backup/b-jonny-20130101');
insert into folder (folder_name,folder_path) values ('b-jonny-20130103','/archive/backup/b-jonny-20130103');
insert into folder (folder_name,folder_path) values ('b-hanna-20140101','/archive/backup/b-jonny-20140101');
insert into folder (folder_name,folder_path) values ('b-mary-20120303','/archive/backup/b-mary-20120303');
I think the only possiblity to do so is via PL/pgSQL:
iterate for folder_name in FOLDER over every row in OWNER
check for every ident_string to lookup the owner_id.
Could somebody help me out?

Maybe something similar to the following?
update folder set folder.owner_id = owner.owner_id from folder join owner on folder_name like owner.ident_string + '%'
(like is the method for regexs in sql)

Try this:
update folder as f
set owner_id = o.owner_id
from owner as o
where o.ident_string = left(f.folder_name,length(o.ident_string));
-g

You could create table folder in one sentence:
insert into folder (folder_name,folder_path,owner_id)
with tmp (folder_name,folder_path) as
(
select 'b-jonny-20130101','/archive/backup/b-jonny-20130101' union all
select 'b-jonny-20130103','/archive/backup/b-jonny-20130103' union all
select 'b-hanna-20140101','/archive/backup/b-jonny-20140101' union all
select 'b-mary-20120303','/archive/backup/b-mary-20120303'
)
select folder_name,folder_path,o.owner_id
from tmp
join owner o
on tmp.folder_name ~ o.ident_string;
select * from owner;
Use a regular expression (~), it's more powerful.
See SQL FIDDLE DEMO

Related

variables in complex sql queury/rule

I want to insert values into a view, which is over multiple tables. I use Postgresql.
My solution is to write a rule which inserts all the data into the right table and adds the foreign keys into the rows.
My question is: Can I somehow declare variables into the rule for recurring select-statements?
The code for the rule is:
create rule insert_new_user as on insert to "collHBRS".loginview do instead(
-- add email_address to email table
insert into "collHBRS".email(email_addr) values (new.login_name);
-- add new empty profile to profile table
insert into "collHBRS".profile(profile_email_fk, profile_address_fk, profile_student_fk, profile_company_fk)
VALUES (
(select email_id from "collHBRS".email where email_addr = new.login_name), -- get email_fk
null,null,null);
-- create new login
insert into "collHBRS".login(login_email_fk, login_password, login_salt, last_login, login_profile_fk)
values (
(select email_id from "collHBRS".email where email_addr = new.login_name), -- get email_fk
new.login_password,new.login_salt,now(),
(select profile_id from "collHBRS".profile where profile_email_fk =
(select email_id from "collHBRS".email where email_addr = new.login_name) -- get profile_fk with email_fk
)
)
);
I repeat the select-statement to get the primary key from my new email entry like 2 times.
(select email_id from "collHBRS".email where email_addr = new.login_name)
I tried it, with DECLARE and WITH AS.
The rule works, it is just not pretty.
Thank you

How do I create a variable/parameter that is a string of values in SQL SSMS that I can use as a substitute in my where clause?

This may be a very basic question, but I have been struggling with this.
I have a SSMS query that I'll be using multiple times for a large set of client Ids. Its quite cumbersome to have to amend the parameters in all the where clauses every time I want to run it.
For simplicity, I want to convert a query like the one below:
SELECT
ID,
Description
From TestDb
Where ID in ('1-234908','1-345678','1-12345')
to a query of the format below so that I only need to change my variable field once and it can be applied across my query:
USE TestDb
DECLARE #ixns NVARCHAR(100)
SET #ixns = '''1-234908'',''1-345678'',''1-12345'''
SELECT
ID,
Description
From TestDb
Where ID IN #ixns
However, the above format doesn't work. Can anyone help me on how I can use a varchar/string variable in my "where" clause for my query so that I can query multiple IDs at the same time and only have to adjust/set my variable once?
Thanks in advance :D
The most appropriate solution would be to use a table variable:
DECLARE #ixns TABLE (id NVARCHAR(100));
INSERT INTO #ixns(id) VALUES
('1-234908'),
('1-345678'),
('1-12345');
SELECT ID, Description
FROM TestDb
WHERE ID IN (SELECT id FROM #ixns);
You can load ids to temp table use that in where condition
USE TestDb
DECLARE #tmpIDs TABLE
(
id VARCHAR(50)
)
insert into #tmpIDs values ('1-234908')
insert into #tmpIDs values ('1-345678')
insert into #tmpIDs values ('1-12345')
SELECT
ID,
Description
From TestDb
Where ID IN (select id from #tmpIDs)
The most appropriate way is to create a table type because it is possible to pass this type as parameters.
1) Creating the table type with the ID column.
create type MyListID as table
(
Id int not null
)
go
2) Creating the procedure that receives this type as a parameter.
create procedure MyProcedure
(
#MyListID as MyListID readonly
)
as
select
column1,
column2
...
from
MyTable
where
Id in (select Id from #MyListID)
3) In this example you can see how to fill this type through your application ..: https://stackoverflow.com/a/25871046/8286724

Does sqlite has something like case on procedural Level?

I have a simple, as it looks, question:
I am having Sqlite query where I am using temp tables and then joining those table, something like:
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
Now is it possible to create some sort of procedura if or case so for example one of those insert will not be executed, like:
bool merge = false;
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
if(merge)
{
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
else
{
select * from SourceA
}
Example of usage is simple, its like a condition when you determine seconds two dates, let's say second table counts missing seconds, so now if interval is too big app will crush. So i need to determine outside of SQL if such thing can be done, and pass it to SQL (basically it can be any condition that will exclude second insert from happening)
I've mange to handle my problem by using variables temp table like:
drop table if exists Variables;
create temp table Variables (MinDatetime Datetime, MaxDatetime Datetime);
insert into Variables Values(#MinDatetime, #MaxDatetime);
And then passing parameter from code, an just omitting result using case something like:
case when (Select MinDatetime from Variables) = 'None' or (Select MaxDatetime from Variables) = 'None' then 0
else value
end as value
And if value is 'None' it will return just plain 0
SQLite is designed as an embedded database, to be used together with a 'real' programming language, so it does not have any procedural features.
Put the control logic into your actual program (or, if you don't have one, write a script).

Create a global variable list/set in sql server

DECLARE #Companies_List char(25)
SET #Companies_List = ('Amazon','Google','Facebook')
select *
from companies
where name in #Companies_List
I'm new to SQL Server. I'm trying to create a global set containing the values that I want to use in the SQL where clause, but apparently the above script wouldn't work. Any idea how I should do it? Many thanks!
I would create a TABLE variable and do a JOIN to it for a list like this:
DECLARE #Companies_List TABLE
(
Name Char(25)
)
INSERT #Companies_List (Name)
VALUES ('Amazon'), ('Google'), ('Facebook')
SELECT C.*
FROM Companies C
JOIN #Companies_List CL ON C.Name = CL.Name
If you want something more concrete, you should make a physical TABLE.

Declare variable in SQLite and use it

I want to declare a variable in SQLite and use it in insert operation.
Like in MS SQL:
declare #name as varchar(10)
set name = 'name'
select * from table where name = #name
For example, I will need to get last_insert_row and use it in insert.
I have found something about binding but I didn't really fully understood it.
SQLite doesn't support native variable syntax, but you can achieve virtually the same using an in-memory temp table.
I've used the below approach for large projects and works like a charm.
/* Create in-memory temp table for variables */
BEGIN;
PRAGMA temp_store = 2; /* 2 means use in-memory */
CREATE TEMP TABLE _Variables(Name TEXT PRIMARY KEY, RealValue REAL, IntegerValue INTEGER, BlobValue BLOB, TextValue TEXT);
/* Declaring a variable */
INSERT INTO _Variables (Name) VALUES ('VariableName');
/* Assigning a variable (pick the right storage class) */
UPDATE _Variables SET IntegerValue = ... WHERE Name = 'VariableName';
/* Getting variable value (use within expression) */
... (SELECT coalesce(RealValue, IntegerValue, BlobValue, TextValue) FROM _Variables WHERE Name = 'VariableName' LIMIT 1) ...
DROP TABLE _Variables;
END;
For a read-only variable (that is, a constant value set once and used anywhere in the query), use a Common Table Expression (CTE).
WITH const AS (SELECT 'name' AS name, 10 AS more)
SELECT table.cost, (table.cost + const.more) AS newCost
FROM table, const
WHERE table.name = const.name
SQLite WITH clause
Herman's solution works, but it can be simplified because Sqlite allows to store any value type on any field.
Here is a simpler version that uses one Value field declared as TEXT to store any value:
CREATE TEMP TABLE IF NOT EXISTS Variables (Name TEXT PRIMARY KEY, Value TEXT);
INSERT OR REPLACE INTO Variables VALUES ('VarStr', 'Val1');
INSERT OR REPLACE INTO Variables VALUES ('VarInt', 123);
INSERT OR REPLACE INTO Variables VALUES ('VarBlob', x'12345678');
SELECT Value
FROM Variables
WHERE Name = 'VarStr'
UNION ALL
SELECT Value
FROM Variables
WHERE Name = 'VarInt'
UNION ALL
SELECT Value
FROM Variables
WHERE Name = 'VarBlob';
Herman's solution worked for me, but the ... had me mixed up for a bit. I'm including the demo I worked up based on his answer. The additional features in my answer include foreign key support, auto incrementing keys, and use of the last_insert_rowid() function to get the last auto generated key in a transaction.
My need for this information came up when I hit a transaction that required three foreign keys but I could only get the last one with last_insert_rowid().
PRAGMA foreign_keys = ON; -- sqlite foreign key support is off by default
PRAGMA temp_store = 2; -- store temp table in memory, not on disk
CREATE TABLE Foo(
Thing1 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
);
CREATE TABLE Bar(
Thing2 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
FOREIGN KEY(Thing2) REFERENCES Foo(Thing1)
);
BEGIN TRANSACTION;
CREATE TEMP TABLE _Variables(Key TEXT, Value INTEGER);
INSERT INTO Foo(Thing1)
VALUES(2);
INSERT INTO _Variables(Key, Value)
VALUES('FooThing', last_insert_rowid());
INSERT INTO Bar(Thing2)
VALUES((SELECT Value FROM _Variables WHERE Key = 'FooThing'));
DROP TABLE _Variables;
END TRANSACTION;
To use the one from denverCR in your example:
WITH tblCTE AS (SELECT "Joe" AS namevar)
SELECT * FROM table, tblCTE
WHERE name = namevar
As a beginner I found other answers too difficult to understand, hope this works
Creating "VARIABLE" for use in SQLite SELECT (and some other) statements
CREATE TEMP TABLE IF NOT EXISTS variable AS SELECT '2002' AS _year; --creating the "variable" named "_year" with value "2002"
UPDATE variable SET _year = '2021'; --changing the variable named "_year" assigning "new" value "2021"
SELECT _year FROM variable; --viewing the variable
SELECT 'TEST', (SELECT _year FROM variable) AS _year; --using the variable
SELECT taxyr FROM owndat WHERE taxyr = (SELECT _year FROM variable); --another example of using the variable
SELECT DISTINCT taxyr FROM owndat WHERE taxyr IN ('2022',(SELECT _year FROM variable)); --another example of using the variable
DROP TABLE IF EXISTS variable; --releasing the "variable" if needed to be released
After reading all the answers I prefer something like this:
select *
from table, (select 'name' as name) const
where table.name = const.name
Try using Binding Values. You cannot use variables as you do in T-SQL but you can use "parameters". I hope the following link is usefull.Binding Values
I found one solution for assign variables to COLUMN or TABLE:
conn = sqlite3.connect('database.db')
cursor=conn.cursor()
z="Cash_payers" # bring results from Table 1 , Column: Customers and COLUMN
# which are pays cash
sorgu_y= Customers #Column name
query1="SELECT * FROM Table_1 WHERE " +sorgu_y+ " LIKE ? "
print (query1)
query=(query1)
cursor.execute(query,(z,))
Don't forget input one space between the WHERE and double quotes
and between the double quotes and LIKE