SSIS Mysql dataflow multiple statement source - mysql

I am running into problems with SSIS(2012), mysql(odbc) and dataflow when my sql command is more than one statement. In addition I cannot start the statement with a comment either. This is not a problem when using oledb & sql server.
SELECT id FROM id_table WHERE type = 'product' INTO #id;
SELECT name FROM products WHERE id = #id;
This isn't the most relevant example. It's just to show what I'm doing. But this will not work with Mysql(ODBC) as my source. I get the following:
Table has no columns
My work around is using a sub query:
SELECT name FROM products WHERE id = (SELECT id from id_table WHERE type = 'product');
Also the below with a comment comes up with the same error:
/* Test comment */
SELECT name FROM products WHERE id = (SELECT id from id_table WHERE type = 'product');
Again, sql server(OLEDB), haven't tried ODBC, has no problems with either case.
My first thought is to check the driver and enable the "Multiple statements" flag, which is already checked. Is there a solution to this in the settings of the driver or in SSIS?
EDIT:
Additional examples:
This works with sql server and odbc source for a dataflow:
DECLARE #offer AS VARCHAR(8)
SET #offer = 'WDWD' + CONVERT(VARCHAR,1000 + DATEPART(wk,GETDATE()))
SELECT * FROM source WHERE cd = #offer
The rough equivalent with mysql and odbc source for a dataflow does not:
SET #offer = CONCAT('WHW410', LPAD(WEEKOFYEAR(NOW()), 2, '0'));
SELECT * FROM source WHERE cd = #offer;
I verified both of these are valid sql in SSMS and sqlyog.

Related

JOOQ multiset throwing syntax exception

Recently moved to JOOQ 3.15.5 and tried the Multiset feature but it is throwing SQLSyntaxErrorException. Below is the query I wrote:
dslContext.select(
tableA.asterisk(),
multiset(
select(tableB.DELETED, tableB.VALUE)
.from(tableB)
.where(tableB.ORDER_ID.eq(tableA.ORDER_ID))
).as("bookingAdditions")
).from(tableA)
.where(tableA.BATCH_ID.greaterThan(batchId))
.fetchInto(BookingDto.class);
Here is the relations:
|tableA| 1 n |tableB|
| | --------------> | |
| | | |
-------- --------
(tableA) (tableB)
Here is the query that is being generated by JOOQ:
set #t = ##group_concat_max_len; set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > 0; set ##group_concat_max_len = #t;
Here are exceptions:
org.jooq.exception.DataAccessException: SQL [set #t = ##group_concat_max_len; set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array(`v0`, `v1`) separator ','), ']')), json_array()) from (select `tableb`.`deleted` as `v0`, `tableb`.`value` as `v1` from `db_name`.`booking_additions` as `tableb` where `tableb`.`order_id` = `tablea`.`order_id`) as `t`) as `bookingadditions` from `db_name`.`booking` as `tablea` where `tablea`.`batch_id` > ?; set ##group_concat_max_len = #t;]; You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'set ##group_concat_max_len = 4294967295; select `tablea`.*, (select coalesce(jso' at line 1
at org.jooq_3.15.5.MYSQL.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2988)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:639)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:295)
at org.jooq.impl.AbstractResultQuery.fetchLazyNonAutoClosing(AbstractResultQuery.java:316)
at org.jooq.impl.SelectImpl.fetchLazyNonAutoClosing(SelectImpl.java:2866)
at org.jooq.impl.ResultQueryTrait.collect(ResultQueryTrait.java:357)
at org.jooq.impl.ResultQueryTrait.fetchInto(ResultQueryTrait.java:1423)
at com.company.BookingDAO.fetchBookings(BookingDAO.java:118)
at
I am using Mysql: 5.7. What am I doing wrong? Any hint?
jOOQ generates three SQL statements separated by semicolons when you use GROUP_CONCAT() in a query. Unfortunately, the default behavior of MySQL is to disallow multiple queries in a single request.
You have to change your JDBC connection options to include allowMultiQueries.
Read more about it here: https://blog.jooq.org/mysqls-allowmultiqueries-flag-with-jdbc-and-jooq/
Regarding the multiple statements
In addition to what Bill Karwin said, you could also specify the Settings.renderGroupConcatMaxLenSessionVariable to be false and increase your server's ##group_concat_max_len variable for your session or your server yourself.
jOOQ's default here is to assume it's easier to add the JDBC connection flag rather than change the server settings, but both approaches are viable.
Regarding correlated derived tables
This particular emulation requires support for correlated derived tables, which MySQL 5.7 doesn't support, see https://github.com/jOOQ/jOOQ/issues/12045. You're not going to get a correlated MULTISET expression to work on MySQL 5.7, but you could write an almost equivalent MULTISET_AGG expression, like this:
dslContext.select(
tableA.asterisk(),
multisetAgg(tableB.DELETED, tableB.VALUE).as("bookingAdditions")
).from(tableA)
.join(tableB).on(tableB.ORDER_ID.eq(tableA.ORDER_ID))
.where(tableA.BATCH_ID.greaterThan(batchId))
// You can group by the primary key, or tableA.fields() if you don't have a PK
.groupBy(tableA.ID)
.fetchInto(BookingDto.class);
Unlike MULTISET, MULTISET_AGG produces NULL values instead of empty lists in case you're left joining tableB, as is usual for SQL aggregate functions. You could then use coalesce(multisetAgg(...), multiset(...)) as a workaround.

Update and select in single query . Sql syntax error in Scala

I am trying to query the database using the below query. It works fine when I run the query in mysql server. But when I run the same query in scala it throws error.
I want to get a single row in db whose cid_status is "unreserved" and cid_curprocess is 'process1'and update the same cid_status to "reserved" and get back the cid_issueid of that row
Below is the query.
val query = "SET #LastUpdateID := 0; UPDATE table_details INNER JOIN
(SELECT cid_issueid FROM cen_issue_details WHERE
cid_curprocess='process1' AND cid_status='unreserved' LIMIT 1) AS
final ON cen_issue_details.cid_issueid=final.cid_issueid SET
cen_issue_details.cid_status ='reserved',cen_issue_details.cid_issueid
= (SELECT #LastUpdateID := cen_issue_details.cid_issueid);SELECT #LastUpdateID AS LastUpdateID;
val rs = statement.executeUpdate(query)
I get the below error:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE table_details INNER JOIN (SELECT cid_issueid FROM cen_issue_details W' at line 1
Also I am not sure whether to use executeUpdate or executeQuery since the query does both SELECT and UPDATE.
Statement.executeupdate(String) accepts only a single statement, but you have provided two.
See the docs at https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeUpdate(java.lang.String)
This question discusses the options for doing multiple statements in a single roundtrip with JDBC: Two different prepared statements in one single batch

SQLite / MySQL compatibility issue

I know SQL in SQLite is not completely implemented the same way as in MySql. My problem with the following queries is, that they are not compatible and I like to avoid a conditional if <DBMS> ... else
SQLite query
UPDATE sorties SET state = '#'
WHERE `key` IN (
SELECT `key` FROM sorties
INNER JOIN reports AS r
ON r.sortieId=sorties.`key`);
Error on MySQL:
SQL Error (1093): Table 'sorties' is specified twice, both as a target for 'UPDATE' and as a separate source for data
MySQL query (adapted from here)
UPDATE sorties AS s SET s.state='#'
WHERE s.`key` IN (
SELECT t.sortieId FROM (
SELECT r.sortieId AS sortieId
FROM reports AS r
INNER JOIN sorties AS sort
ON sort.`key`=r.sortieId)
AS t);
Error on SQLite:
SQLiteManager: Likely SQL syntax error: UPDATE sorties AS s SET s.state='#'
WHERE s.key IN ( SELECT t.sortieId FROM (
SELECT DISTINCT r.sortieId AS sortieId
FROM reports AS r
INNER JOIN sorties AS sort
ON sort.key=r.sortieId) AS t); [ near "AS": syntax error ]
Exception Name: NS_ERROR_FAILURE
Exception Message: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [mozIStorageConnection.createStatement]
I can't figure out how to make this queries work on both systems equally!
All I want to have is, that each state of sorties must be '#' when it's key can be found in reports.sortieId.
Maybe there is a different approach for this?
Thank you
The first command reads the key value from the sorties table in the subquery, and then checks whether those key values exist in the sorties table in the outer statement. That check is superfluous; you can just compare the values to the ones in reports directly:
UPDATE sorties
SET state = '#'
WHERE key IN (SELECT sortieId
FROM reports);
As for the second command, SQLite does not support aliasing a table used in INSERT/UPDATE/DELETE because those commands work only on a single table. You can just remove the AS s and replace s with sorties everywhere.

SSIS - Replace Dynamic SQL With Variables

in my dataflow task I have OLEDB Source with the following query:
SELECT am.Code AS MeterCode
,am.Code AS NewMeterCode
,am.Description AS NewMeterDescription
,mr.TagName
,mr.RunHours
,mr.DateTo AS DateRead
FROM [19-AIS-004\VIJEOHISTORIAN].VijeoHistorianCPSData.dbo.RunHours AS mr
INNER JOIN dbo.astMeters AS am ON mr.TagName COLLATE SQL_Latin1_General_CP1_CI_AS = am.Code
the table 'mr' is the linked server table where i'm getting the Tagname, Runhours and DateTo and join it with astMeters table in order to import data from mr table to am table.
my problem is since the package is deployed in the remote server via vpn I need a way which I can created string parameter for the this table '[19-AIS-004\VIJEOHISTORIAN].VijeoHistorianCPSData.dbo.RunHours'.
Build your entire query as an SSIS string variable, and in your OLEDB Source, choose SQL Query From Variable and select the string variable that holds your query.

Using System/User Variables as Parameters in an OLE DB Source Query

I have got a SQL command like the following :
SELECT *
FROM temp1 a
inner join (SELECT ID from temp2 where ID = ?) b on a.ID = b.ID
WHERE a.ID = ?
I know the query has incorrect logic. But my question is How will I set Variables as parameters here in the place of "?". If I exclude the joined part, it will work.
Edit the OLE DB Source. On the Connections Manager tab, click the Parameters... button. The Parameters dialog will display the parameters in the sequence they appear in the SQL statement. The sequence is determined by reading the SQL statement from left-to-right, top-to-bottom.
To make an assignment to a parameter, select the variable from the Variables column.