Qr code scanner PostgreSQL Database Validation - postgresql

I'm creating a very basic qr code scanner entrance database system with postgresql
2 tables:
Table "persons" include a list of all participants with: id, first_name, last_name, email, phone, qr_code
Table "check_ins" include a list of all the people who entered the event: id, person_id, check_in_time
I created this query:
INSERT INTO check_ins (person_id)
SELECT id
FROM persons
WHERE qr_code = {{ scanner1.data[0]}} AND
EXISTS (SELECT * FROM persons WHERE qr_code = {{ scanner1.data['0']}})
{{ scanner1.data[0]}} is the scanner input value
The query still work for qr_code that aren't present in table persons. I'm expecting an error (I have a popup that trigger if the query is a failure with a text "Qr Code Already scanned or Invalid")
I'm expecting this:
qr_code scanned present in table persons but not in table check_ins = insert in table check_ins | query run successfully
qr_code scanned not present in table persons = query failure
qr_code scanned present in table persons but also in table check_ins = query failure
I structured the app so when the query run successfully a text will appear with "Qr code valid" and when not "Qr code already scanned or invalid"

This query returns either the id of the new check_ins record or an empty resultset (nothing was inserted because either t CTE had no record in it or this person_id already existed in check_ins).
So you can distinguish success from failure by the result.
with t(pid) as
(
SELECT id FROM persons
WHERE qr_code = {{ scanner1.data['0']}}
)
INSERT INTO check_ins (person_id)
SELECT pid from t
WHERE NOT EXISTS (SELECT FROM check_ins WHERE person_id = t.pid)
RETURNING id;

Related

SQL join table with a dynamic database name

I have a table which contains a employee ID and a database ID code in database DBX0 table 'FirstTable':
Employee ID
Database ID
123
1
456
2
789
2
149
3
The database name is stored in a different table 'databases' like :
Database ID
DB name
1
DBX1
2
DBX2
3
DBX3
So what I'm trying to do is join the first table with a separate table which is stored in the identified database, like
SELECT * from DBX0.dbo.FirstTable a join (SELECT [DB name] from DBX0.dbo.databases where [database ID] = a.[database ID]).dbo.OtherTable
(I don't think this will actually work with a subquery, but this would return the result that I want in theory.)
I have tried dynamic sql with a cursor to iterate through each database and then only return results based on database ID = database ID and Employee ID = Employee ID, but this returns the results in a separate result per database.
Also tried:
Select * from (SELECT * from DBX0.dbo.FirstTable a join '+#dbname+'.dbo.OtherTable on a.employeeid = b.employeeid and a.dbid = b.dbid)
in dynamic sql, but this didn't work either.
Is there any way to get all of the data in one result?

Bulk INSERT for records that don't exist, returning ID

I'm using pg-promise to process an array of data that I want to insert in table A. I'm having a hard time figuring out how to dynamically create this query that should only INSERT those values not already present in the table, while returning the ID of all those who are already present or were newly created.
I'm doing the following to do the above, but for a single element:
WITH s as
( SELECT *
FROM fruits
WHERE fruit_name = 'Apple' ),
i AS
( INSERT INTO fruits(fruit_name) SELECT 'Apple'
WHERE NOT exists
(SELECT 1
FROM s) RETURNING fruit_id)
But say that I have an Array of fruits = ['Banana', 'Apple']. How would I use the helpers to generate a query that would return the existing ID for apple, and the one for Banana?

Perform search based on seperate table data in PostgreSQL

I have a table which looks like this:
deals
id vendorid name
1 52 '25% Off'
2 34 '10% Off'
-
vendors
id name
52 'Walmart'
34 'Home Depot'
I'm trying to do a search of the database that also searches based on the vendor id.
I was able to do this to get the vendor data in the query:
SELECT *,
(SELECT json_agg(vendors.*) FROM vendors WHERE deals.vendorid = vendors.id) as vendor
FROM deals
Now I want to add a search to it, here is something I tried
SELECT *,
(SELECT json_agg(vendors.*) FROM vendors WHERE deals.vendorid = vendors.id) as vendor
FROM deals
WHERE vendor.name ILIKE '%wal%'
In the above example the user would be starting a search for walmart however it says that the vendor.name column does not exist, what would the correct way to do this be?
The output I'm expecting from the above query is:
[
{
id: 1,
vendorid: 52,
name: '25% Off',
vendor: [
{
id: 52,
name: 'Walmart'
}
]
}
]
I was able to get it done by using this.
SELECT
*,
(SELECT json_agg(vendors.*) FROM vendors WHERE deals.vendorid = vendors.id) as vendor
FROM
deals
where (SELECT json_agg(vendors.*) FROM vendors WHERE deals.vendorid = vendors.id).name ILIKE '%wal%'
It's pretty ugly but get the work done. I am not really familiar with postgree but you can store it in a variable somehow.
The query you need
drop table if exists deals;
drop table if exists vendors;
create table if not exists deals(
id serial,
vendorid int not null,
name varchar not null
);
create table if not exists vendors(
id serial,
name varchar not null
);
insert into deals values
(1,52,'25% off'),
(2,34,'10% off');
insert into vendors values
(52,'Walmart'),
(34,'Home Depot');
select
d.id,
d.vendorid,
v.name,
json_agg(v.*)
from
vendors v
left join
deals d on d.vendorid = v.id
where
--v.id=52 and
v.name ILIKE '%wal%'
group by
d.id,
d.vendorid,
v.name;
If you are running a 9.3+ version of postgres, you can use a great feature provided by postgres : the full text search
check how it works here
Enjoy postgres power.

Insert multiple rows where not exists PostgresQL

I'd like to generate a single sql query to mass-insert a series of rows that don't exist on a table. My current setup makes a new query for each record insertion similar to the solution detailed in WHERE NOT EXISTS in PostgreSQL gives syntax error, but I'd like to move this to a single query to optimize performance since my current setup could generate several hundred queries at a time. Right now I'm trying something like the example I've added below:
INSERT INTO users (first_name, last_name, uid)
SELECT ( 'John', 'Doe', '3sldkjfksjd'), ( 'Jane', 'Doe', 'adslkejkdsjfds')
WHERE NOT EXISTS (
SELECT * FROM users WHERE uid IN ('3sldkjfksjd', 'adslkejkdsjfds')
)
Postgres returns the following error:
PG::Error: ERROR: INSERT has more target columns than expressions
The problem is that PostgresQL doesn't seem to want to take a series of values when using SELECT. Conversely, I can make the insertions using VALUES, but I can't then prevent duplicates from being generated using WHERE NOT EXISTS.
http://www.techonthenet.com/postgresql/insert.php suggests in the section EXAMPLE - USING SUB-SELECT that multiple records should be insertable from another referenced table using SELECT, so I'm wondering why I can't seem to pass in a series of values to insert. The values I'm passing are coming from an external API, so I need to generate the values to insert by hand.
Your select is not doing what you think it does.
The most compact version in PostgreSQL would be something like this:
with data(first_name, last_name, uid) as (
values
( 'John', 'Doe', '3sldkjfksjd'),
( 'Jane', 'Doe', 'adslkejkdsjfds')
)
insert into users (first_name, last_name, uid)
select d.first_name, d.last_name, d.uid
from data d
where not exists (select 1
from users u2
where u2.uid = d.uid);
Which is pretty much equivalent to:
insert into users (first_name, last_name, uid)
select d.first_name, d.last_name, d.uid
from (
select 'John' as first_name, 'Doe' as last_name, '3sldkjfksjd' as uid
union all
select 'Jane', 'Doe', 'adslkejkdsjfds'
) as d
where not exists (select 1
from users u2
where u2.uid = d.uid);
a_horse_with_no_name's answer actually has a syntax error, missing a final closing right parens, but other than that is the correct way to do this.
Update:
For anyone coming to this with a situation like mine, if you have columns that need to be type cast (for instance timestamps or uuids or jsonb in PG 9.5), you must declare that in the values you pass to the query:
-- insert multiple if not exists
-- where another_column_name is of type uuid, with strings cast as uuids
-- where created_at and updated_at is of type timestamp, with strings cast as timestamps
WITH data (id, some_column_name, another_column_name, created_at, updated_at) AS (
VALUES
(<id value>, <some_column_name_value>, 'a5fa7660-8273-4ffd-b832-d94f081a4661'::uuid, '2016-06-13T12:15:27.552-07:00'::timestamp, '2016-06-13T12:15:27.879-07:00'::timestamp),
(<id value>, <some_column_name_value>, 'b9b17117-1e90-45c5-8f62-d03412d407dd'::uuid, '2016-06-13T12:08:17.683-07:00'::timestamp, '2016-06-13T12:08:17.801-07:00'::timestamp)
)
INSERT INTO table_name (id, some_column_name, another_column_name, created_at, updated_at)
SELECT d.id, d.survey_id, d.arrival_uuid, d.gf_created_at, d.gf_updated_at
FROM data d
WHERE NOT EXISTS (SELECT 1 FROM table_name t WHERE t.id = d.id);
a_horse_with_no_name's answer saved me today on a project, but had to make these tweaks to make it perfect.

Iterating through a TVP before inserting records?

I'd like some help writing the following sproc:
I have SQL Server 2008 sproc that accepts two integer values (#ID1 and #ID2) and a data table/TVP.
The TVP table contains several fields, ie. Title and Description.
I want to iterate through the TVP table and check if the Title or Description already exists in my data table, tbl_Items, where #ID1 = tbl_Items.ID1 and #ID2 = tbl_Items.ID2.
If neither exist then insert the values of #ID1 and ID2 and that TVP row into tbl_Items.
Thanks.
Something like this?
INSERT INTO tbl_Items (ID1, ID2, Title, Description)
SELECT
#ID1, #ID2, TVP.Title, TVP.Description
FROM
#TVP AS TVP
WHERE
NOT EXISTS (SELECT * FROM tbl_Items AS I WHERE TVP.Title = I.Title AND TVP.Description = I.Description)
The requirement seems somewhat unclear but you should be able to use MERGE
;WITH Target As
(
SELECT *
FROM tbl_Items
WHERE ID1=#ID1 AND ID2=#ID2
)
MERGE
INTO Target
USING #TVP AS Source
ON Target.Title = Source.Title OR Target.Description = Source.Description
WHEN NOT MATCHED
THEN INSERT (ID1, ID2, Title, Description)
VALUES (#ID1, #ID2, Title, Description)