jOOQ insert into .. where not exists for Postgres - postgresql

I'm attempting to do an upsert-style statement for Postgres in jOOQ. The framework I'm running in takes care of concurrency concerns in this specific situation so I'm not worried about that. I'm only using jOOQ for creating the SQL, the actual execution is done via Spring's JdbcTemplate and a BeanPropertySqlParameterSource.
I've decided to go with a two-step "insert..where not exists" / "update .." process.
My SQL is:
insert into mytable (my_id, col1, col2) select :myId,
:firstCol, :secondCol where not exists (select 1
from mytable where my_id = :myId)
I'm using Postgres 9.4, jOOQ 3.5. I'm not sure how to express both the jOOQ params in the select and the "where not exists" clause in jOOQ.
Suggestions to change programming languages or databases aren't viable in my situation.

If you want to reuse a named parameter in jOOQ, ideally, you create the AST element outside of the query, as such:
// Assuming a static import
import static org.jooq.impl.DSL.*;
Param<Integer> myId = param("myId", Integer.class);
You can then use it multiple times in your query:
using(configuration)
.insertInto(MY_TABLE, MY_TABLE.MY_ID, MY_TABLE.COL1, MY_TABLE.COL2)
.select(
select(
myId,
param("firstCol", MY_TABLE.COL1.getType()),
param("secondCol", MY_TABLE.COL2.getType())
)
.whereNotExists(
selectOne()
.from(MY_TABLE)
.where(MY_TABLE.MY_ID.eq(myId))
)
);

Related

can we use CTE inside DB2 LUW trigger

i am using DB2 LUW version 10.x
My question is can we use common table expression inside before insert trigger.
CREATE OR REPLACES TRIGGER TRG_TEST
BEFORE INSERT ON TEST
FOR EACH ROW
WHEN(
WITH DS AS (SELECT COUNT(1) FROM TEST)
SELECT 1 FROM DS
)
The CREATE TRIGGER statement documentation topic definitely should describe in more detail, what search-condition is.
Actually a search-condition may contain expressions, and you can use a scalar-fullselect as part of such an expression. But a fullselect can't contain CTE. Only a select-statement can.
So, you can't use CTEs in search-condition. If you really need it, then wrap your CTE in a function call.

updating table rows in postgres using subquery with jooq

I would like to execute and update similar to this:
UPDATE dummy
SET customer=subquery.customer,
address=subquery.address,
partn=subquery.partn
FROM (SELECT address_id, customer, address, partn
FROM dummy) AS subquery
WHERE dummy.address_id=subquery.address_id;
Taken from this answer: https://stackoverflow.com/a/6258586/411965
I found this and wondered if this can auto converted to jooq fluent syntax.
What is the equivalent jooq query? specifically, how do I perform the outer when referencing the subquery?
Assuming you're using code generation, do it like this:
Table<?> subquery = table(
select(
DUMMY.ADDRESS_ID,
DUMMY.CUSTOMER,
DUMMY.ADDRESS,
DUMMY.PARTN
)
.from(DUMMY)
).as("subquery");
ctx.update(DUMMY)
.set(DUMMY.CUSTOMER, subquery.field(DUMMY.CUSTOMER))
.set(DUMMY.ADDRESS, subquery.field(DUMMY.ADDRESS))
.set(DUMMY.PARTN, subquery.field(DUMMY.PARTN))
.from(subquery)
.where(DUMMY.ADDRESS_ID.eq(subquery.field(DUMMY.ADDRESS_ID)))
.execute();
Of course, the query makes no sense it is, because you're just going to touch every row without modifying it, but since you copied the SQL from another answer, I'm assuming your subquery's dummy table is really something else.

SQLAlchemy fast bulk upsert from another table

I would like to insert records into table_a from table_b that don't already exist in table table_a. I already have Postgres SQL code to do this, but now my team has requested that I use an ORM (SQLAlchemy) instead.
INSERT INTO table_a
SELECT
composite_pk1,
composite_pk2,
col_c,
col_d
FROM table_b
ON CONFLICT (
composite_pk1,
composite_pk2
) DO NOTHING
I have nearly a million rows and about 15 columns (not shown in the example). I need this query to be fast, which is why I don't think the solution posted here will work for my use case.
For performance reasons I also want to avoid treating my Python function as a data conduit. I don't want to transfer many rows of table_b over the network to my function just to push them back over the network again to table_a. That is, I would prefer the insert to happen entirely on Postgres, which I already accomplish with my original SQL query.
Probably the fastest way to perform an upsert with the usage of SQLAlchemy ORM is through bulk_update_mappings function, that allows you to upsert merely based on a list of dicts.
But the situation you are describing isn't really an upsert - you want to insert rows, and if there is a conflict - do nothing. No update is being done here, therefore it is a simple insert.
To perform an insert that skips any conflicts is a simple thing in SQLAlchemy (assuming you have your table already defined as a model):
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('your_db_connection_string', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
# example column names
data = [{'col1': result.col1, 'col2': result.col2}
for result in session.query(table_b).all()]
insert_query = insert(table_a).values(data).on_conflict_do_nothing()
session.execute(insert_query)
session.commit()
session.close()

Postgresql to Hsql

I have this postgres table:
CREATE TABLE News (
tags text[](10),
contract varchar(40),
...others
);
I need to get all the distinct tags for a given contract. I found the postgresql request which works well:
SELECT array_agg(acc)
FROM (
SELECT DISTINCT unnest(tags::text[])
FROM my_schema.news
WHERE contract = 'acontract'
) AS dt(acc);
As I am using spring data jpa, I try to convert this request into an HSQL request but I can't make it work. Any idea on what the conversion could be?
In addition to SET DATABASE SQL SYNTAX PGS TRUE you need to reference the arrays according to the SQL standard.
CREATE TABLE News (tags text array[10], contract varchar(40))
Then
select array_agg(acc) from (
select distinct acc from news, unnest(tags) un(acc)
WHERE contract = 'acontract'
)

SQL join from multiple tables

We've got a system (MS SQL 2008 R2-based) that has a number of "input" database and a one "output" database. I'd like to write a query that will read from the output DB, and JOIN it to data in one of the source DB. However, the source table may be one or more individual tables :( The name of the source DB is included in the output DB; ideally, I'd like to do something like the following (pseudo-SQL ahoy)
select o.[UID]
,o.[description]
,i.[data]
from [output].dbo.[description] as o
left join (select [UID]
,[data]
from
[output.sourcedb].dbo.datatable
) as i
on i.[UID] = o.[UID];
Is there any way to do something like the above - "dynamically" specify the database and table to be joined on for each row in the query?
Try using the exec function, then specify the select as a string, adding variables for database names and tables where appropriate. Simple example:
DECLARE #dbName VARCHAR(255), #tableName VARCHAR(255), #colName VARCHAR(255)
...
EXEC('SELECT * FROM ' + #dbName + '.dbo.' + #tableName + ' WHERE ' + #colName + ' = 1')
No, the table must be known at the time you prepare the query. Otherwise how would the query optimizer know what indexes it might be able to use? Or if the table you reference even has an UID column?
You'll have to do this in stages:
Fetch the sourcedb value from your output database in one query.
Build an SQL query string, interpolating the value you fetched in the first query into the FROM clause of the second query.
Be careful to check that this value contains a legitimate database name. For instance, filter out non-alpha characters or apply a regular expression or look it up in a whitelist. Otherwise you're exposing yourself to a SQL Injection risk.
Execute the new SQL string you built with exec() as #user353852 suggests.