ADF SQL Query with single quotes around dates - oracle

I'm trying to do a simple pull from oracle based on a date. Eventually, I need this query to be dynamic hence using #concat() function in ADF. For simplicity sake I want to run the below oracle query in ADF with concat.
Since oracle requires single quotes I'm trying to escape it by using two single quotes.
oracle query:
select * from schema.customer where updated > to_date('06/25/2019','MM/DD/YYYY')
here's my ADF text:
#concat('select * from iris.iris_customer where updated >
to_date(','''06/25/2019''','''MM/DD/YYYY''',');')
I'm using to_date because I was getting the 'not a valid month' error and thought I could resolve it. Here's the error I'm getting:
{
"errorCode": "2200",
"message": "Failure happened on 'Source' side. ErrorCode=UserErrorUnclassifiedError,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=Odbc
Operation
Failed.,Source=Microsoft.DataTransfer.ClientLibrary.Odbc.OdbcConnector,''Type=System.Data.Odbc.OdbcException,Message=ERROR
[22008] [Microsoft][ODBC Oracle Wire Protocol
driver][Oracle]ORA-01843: not a valid month,Source=msora28.dll,'",
"failureType": "UserError",
"target": "copy_to_adl" }

you should use '' for escaping single quote.
My Example: #{concat('DELETE FROM MyTable WHERE [ColumnDate] LIKE','''',pipeline().parameters.processYear,pipeline().parameters.processMonth,'%','''')}

You can also use this SQL Syntax inside Expression builder in ADF Data Flows to escape single quotes:
"SELECT * FROM myTable WHERE Id = {$myVar} AND Gender = 'M'"

Related

Getting invalid identifier SQL query

I am trying to execute next query:
MERGE INTO NOTIFICATION_OBJS p
USING (SELECT
:fcsNotif_id as doc_id,
:OKPD2_code as OKPD2_code,
:OKPD2_name as OKPD2_name,
:quantity_value as quantity,
:purchaseObject_price as price
FROM DUAL
) v
ON (p.doc_id=v.doc_id)
WHEN MATCHED THEN
UPDATE SET
p.OKPD2_code = v.OKPD2_code,
p.OKPD2_name = v.OKPD2_name,
p.quantity_value = v.quantity_value,
p.price = v.price
WHEN NOT MATCHED THEN
INSERT (p.doc_id, p.OKPD2_code, p.OKPD2_name, p.quantity_value, p.price)
VALUES(v.doc_id, v.OKPD2_code, v.OKPD2_name, v.quantity_value, v.price)
I am sending to bind method next dictionary:
{'OKPD2_code': '62.02.30.000', 'OKPD2_name': 'some text', 'purchaseObject_price': '20466982.25', 'quantity_value': '1', 'fcsNotif_id': '18941152'}
But I am getting error:
ORA-00904: "P"."OKPD2_NAME": invalid identifier
All other query with binding are working. Please help me to find error.
There's no OKPD2_NAME column in NOTIFICATION_OBJS table.
If you used double quotes while creating that table (and its columns), you should
recreate the table without double quotes, or
reference the table (and its columns that use mixed case) using double quotes again, specifying case EXACTLY as it was while creating the table
[EDIT, after the screenshot has been uploaded]
Column name really is created using mixed case, so you'll have to reference it exactly like that: "OKPD2_name" paying attention to double quotes and mixed case.
If you use "okpd2_name" or "okPD2_NAME" or anything but "OKPD2_name", it won't work. Once again: get rid of double quotes.

Binding on `statement` not supported in Eloquent 5.1?

I'm new to Laravel and trying to do a string query in Eloquent. I was trying to use DB::statement, but I kept getting errors about placeholders in the query string. It seems I either don't have the syntax right, or bindings are unimplemented or unsupported?
The reason I want to use statement is because I'm doing an INSERT... SELECT, which I haven't been able to find any documentation about in Eloquent.
Here's my code:
$ php artisan tinker
Psy Shell v0.5.2 (PHP 5.6.13-0+deb8u1 — cli) by Justin Hileman
>>> echo \DB::statement('CREATE DATABASE :db', [':db'=>'test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 '?' at line 1 (SQL: CREATE DATABASE :db)'
>>> \DB::statement('CREATE DATABASE ?', ['test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 '?' at line 1 (SQL: CREATE DATABASE test)'
These are the two syntax forms (? and :string) from PDO. Other methods in DB such as select and insert support this, according to the documentation.
The relevant parts of these errors are near '?' at line 1 (SQL: CREATE DATABASE :db) and near '?' at line 1 (SQL: CREATE DATABASE test). MySQL thinks there is an unbound ? in the query string. I didn't even use that syntax in the first query. I'm concluding from that that the bind() method did not correctly bind my placeholders.
This question on Laracasts is asking about the syntax, but there is no accepted answer.
Edit One answer says that statement() doesn't support CREATE. I tried some queries out with SELECT, and got the same results, with both placeholders:
>>> \DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = a)'
>>> \DB::statement('SELECT 1 WHERE \'a\' = :letter', array(':letter'=>'a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 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 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = :letter)'
Actually, you can use create and drop query in DB::statement(), but named bindings is not used in that way.
Here are some queries that will success.
drop and create do not accept bindings.
>>> \Db::statement('create database test')
=> true
>>> \Db::statement('drop database test')
=> true
Do not use backslash and single quotes in the statement
>>> \Db::statement('insert into users (id, name) values (?, ?)', ['1', 'John'])
=> true
DB::statement() only return ture when success, so if you want to see select results, you should use DB::select()
>>> \Db::statement('select * from users')
=> true
>>> \Db::select('select * from users')
=> [
{#770
+"id": 1,
+"name": "John",
},
]
Remove leading : in the second argument.
>>> \Db::statement('update users set name = :name where id = :id', ['id' => 1, 'name' => 'John'])
=> true
You will get affect rows if you use DB::update and DB::delete
>>> \Db::delete('delete from users where id = :id', ['id' => 1])
=> 1
The errors you receive are only indirectly related with Laravels DB::statement() function. They all fail within that method at the line
return $me->getPdo()->prepare($query)->execute($bindings);
within the file vendor/laravel/framework/src/Illuminate/Database/Connection.php
Responsible for that failure is the resulting call to PDO::prepare()
The Docuemenation says:
Parameter markers can represent a complete data literal only. Neither part of literal, nor keyword, nor identifier, nor whatever arbitrary query part can be bound using parameters. For example, you cannot bind multiple values to a single parameter in the IN() clause of an SQL statement.
Also have a look at the user contributed notes at the above php.net documentation. Additionally have a look at Can PHP PDO Statements accept the table or column name as parameter?
Your create examples are not supported by PDO.
The reason your SELECT examples fail is simply due to an invalid syntax.
\DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'))
You are simply missing the FROM clause. This example works perfeclty well at my test computer:
$ret = \DB::statement('SELECT 1 FROM `users` WHERE `username` = ?', ["gregor"]);
But
$ret = \DB::statement('SELECT 1 WHERE `username` = ?', ["testname"]);
Generates the exact error, you receive.
Also note, that \DB::statement does not return any ressources. It just indicates by returning true or false, whether the query suceeded.
Your option is to use DB::raw() within your insert() statement, if you want to use INSERT...SELECT. Some googling will help you, to find the proper solution. Maybe as Starting Points: Raw Queries in Laravel, or How to use raw queries in Laravel
What you're trying to do is passing the table name through binding.
DB::statement('select * from ?',['users'])
which according to this post, it's not possible.
of course if you want to sanitize the data you can use an array of short codes like so:
$tables = ['users','test','another'];
and the query would look something like:
$code = 0;
DB::statement("select * from $tables[$code] where a=?",[2]);
DB::statement("create table $tables[$code]");

JOOQ - query without quotes

I use JOOQ-3.1.0 to generate and execute dynamic queries for Oracle and Postgresql with Spring-4. In a scenario I have a partitioned table, which I need to query using JOOQ. I use DSL.tableByName(vblTablename); where vblTablename is the string received as a string in the query generation method, ex, vbl_default partition(p_04-Dec-14). (The vblTablename pattern differs for different databases, and is configured in the external property file). The JOOQ generates the sql, but with the double-quote around the tablename. The query and error shown below
Query
SELECT COUNT(ID) COUNT FROM "vbl_default partition(p_04-Dec-14)"
where (rts between timestamp '2014-12-04 00:00:00.0' and timestamp '2014-12-05 00:00:00.0' and userid in (2))
Error
ORA-00972: identifier is too long
00972. 00000 - "identifier is too long"
*Cause: An identifier with more than 30 characters was specified.
*Action: Specify at most 30 characters.
Error at Line: 4 Column: 29
Though I have set the below settings on the DefaultDSLContext
Settings settings = new Settings();
settings.setRenderNameStyle(RenderNameStyle.AS_IS);
How do I remove the quote around the table? Any other settings have I missed?
The idea behind DSL.tableByName(String...) is that you provide a table ... by name :-)
What you're looking for is a plain SQL table, via DSL.table(String).
You can write:
// Assuming this import
import static org.jooq.impl.DSL.*;
DSL.using(configuration)
.select(count(VBL_DEFAULT.ID))
.from(table("vbl_default partition(p_04-Dec-14)"))
.where(...);
Or by using the convenient overload SelectFromStep.from(String)
DSL.using(configuration)
.select(count(VBL_DEFAULT.ID))
.from("vbl_default partition(p_04-Dec-14)")
.where(...);
More information about plain SQL in jOOQ can be obtained from this manual page:
http://www.jooq.org/doc/latest/manual/sql-building/plain-sql/
Partition support
Note that support for Oracle partitions is on the roadmap: #2775. If in the mean time you wish to use partitioned tables more often, you could also write your own function for that:
// Beware of the risk of SQL injection, though!
public <R extends Record> Table<R> partition(Table<R> table, String partition) {
return DSL.table("{0} partition(" + partition + ")", table);
}
... and then:
DSL.using(configuration)
.select(count(VBL_DEFAULT.ID))
.from(partition(VBL_DEFAULT, "p_04-Dec-14"))
.where(...);

How to write a query with two ? placeholders in sequence?

I am using a NamedParameterJdbcTemplate, but found that this problem is in the underlying JdbcTemplate class, so I will show the problem as it occurs with the JdbcTemplate (so let's not worry about the safety of the SQL query here).
Here's what I am trying to achieve:
String sql = "SELECT * FROM clients ORDER BY ? ?";
return jdbcTemplate.query(sql,
new Object[] { "name", "ASC" },
new ClientResultSetExtractor());
I expected the first place-holder to be replaced with "name" and the second with "ASC", which would create the valid SQL query:
SELECT * FROM clients ORDER BY name ASC
But unfortunately, running that jdbc query does not work:
ERROR: syntax error at or near "$2" at character 35
STATEMENT: SELECT * FROM clients ORDER BY $1 $2
What am I doing wrong?
EDIT
I had assumed the problem was the two placeholders in sequence, but even when I remove the first one, it still won't accept just the last one, which should tell the query whether to sort in ASC or DESC order. Is this a bug, and if not, why the heck is this not acceptable????
You're trying to use parameters incorrectly.
Parameters are not column names or SQL statement keywords. They're data content (eg., WHERE LastName = ? is a valid parameterized statement, WHERE ? = 'Smith' is not).

Cannot executing a SQL query through ODP.NET - invalid character error

I'm trying to execute a SQL query through ODP.NET to create a table, but I always get an ORA-00911 'invalid character' error. The Errors object in the exception always has the text "ORA-00911: invalid character\n", even if there are no linebreaks in the SQL query itself.
The code I'm executing the SQL is this:
using (OracleConnection conn = new OracleConnection(<connection string>) {
using (OracleCommand command = conn.CreateCommand()) {
conn.Open();
command.CommandText = queryString;
command.ExecuteNonQuery(); // exception always gets thrown here
}
queryString contains a single CREATE TABLE statement, which works fine when executed through SQL Developer
EDIT: the SQL I am executing is this:
CREATE TABLE "TESTSYNC"."NEWTABLE" (
"COL1" NUMBER(*,0) NULL,
"COL2" NUMBER(*,0) NULL
);
with linebreaks removed
Other people have come across this issue - ODP.NET does not support multiple SQL statements in a text command. The solution is to wrap it in a PL/SQL block with EXECUTE IMMEDIATE around each statement. This lack of support for ; seems incredibly boneheaded to me, and has not improved my opinion of the oracle development team.
Furthermore, this seems to be an issue with oracle itself, as I have the same problems with the MS and ODBC oracle clients.
I had this issue for some reason you have to have code on one line.
I had strSQL = "stuff" +
" more stuff"
I had to put it on one line.
strSQL = "stuff more stuff"
It some how reads the cr/lf.
Wrap your sql in a Begin block.
Dim sqlInsert As String = ""
For i = 1 To 10
sqlInsert += "INSERT INTO MY_TABLE (COUNT) VALUES (" & i & "); "
Next
Call ExecuteSql("BEGIN " & sqlInsert & " END;")
Your quotes are OK (it just forces Oracle to treat your object names as case sensitive i.e. upper case the way you've written it) but I'm not at all sure you're allowed to define NUMBER that way with a *.
I wonder if it is the "*" in the sql have you tried the call without an * in the create? I bet it is yet another "feature" of the ODP.Net driver

Resources