I am working in Cold Fusion 11* and I am getting the following error:
ORA-01704: string literal too long.
First off, I received this error and corrected it after looking over several sites by changing my code from:
<cfquery datasource="#dsn#">
update paragraphs
set paragraph_text = #input#
where paragraph_id=#rs_d.paragraph_id#
</cfquery>
To:
<cfquery datasource="#dsn#">
update paragraphs
set paragraph_text = <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#input#>
where paragraph_id=#rs_d.paragraph_id#
</cfquery>
That fix worked perfectly. Now I am getting the same error, but instead of using cfquery, I am building the sql query into a string before working with it. So this is how the code looks:
sql = "insert into log (LOG_ENTRY_ID, program_id, paragraph_id, action, userid,";
sql = sql & " paragraph_text_old, paragraph_text_new, comment_id, current_program_status, new_program_status)";
sql = sql & " values (1 ," & program_id & ",";
if (paragraph_id neq ""){
sql = sql & paragraph_id & ",";
}
else{
sql = sql & " null,";
}
sql = sql & "'" & action & "',";
sql = sql & userid & ", '";
sql = sql & DoubleSingleQuotes(paragraph_text_old) & "','";
sql = sql & DoubleSingleQuotes(paragraph_text_new) & "',";
if (comment_id neq ""){
sql = sql & comment_id & ",";
}
else{
sql = sql & " null,";
}
if (current_program_status neq ""){
sql = sql & "'" & current_program_status & "',";
}
else{
sql = sql & " null,";
}
if (new_program_status neq ""){
sql = sql & "'" & new_program_status & "'";
}
else{
sql = sql & " null";
}
sql = sql & ")";
cfstmt(sql);
---End function
<cffunction name="cfstmt">
<cfargument name="sql">
<cfquery name="rs" datasource="#dsn#">
#PreserveSingleQuotes(sql)#
</cfquery>
</cffunction>
The cause of the error is old_paragraph_text and new_paragraph_text. I was wondering if it is possible to include a cfqueryparam type solution to this problem like in the previous problem/solution I included. I tried including it straight like the first one but I am getting compilation errors in the code. Any thoughts or tips would be helpful, thanks.
(Too long for comments)
wanted to limit the code so instead of determining the null value
outside the query, I added the case statements
Honestly, it does not save much, since the code is essentially doing an if/else either way. Except now the work is done on the db side, instead of the app server where it belongs.
Having worked with a lot of legacy apps, I realize they often incorporate what you might euphemistically call "questionable" code ;-) However, you should never use raw client variables in SQL. Unless you have a very good reason to do otherwise, always use cfqueryparam.
Internally, cfqueryparam uses bind variables. Two of the most important benefits are:
Bind variables help protect against sql injection, by preventing the literal values from being executed as SQL commands. This protects the database from values containing maliciously crafted SQL.
For queries executed multiple times, bind variables also boost performance by encouraging the database to reuse execution plans. Otherwise, the database may choose to generate a new execution plan when the query parameters change, which is costly.
CFQueryparam also has some other nice features, such as the "null" attribute. It can be used to submit a null value when certain conditions are met.
Finally, in terms of best practices, it is also a good idea to fully scope all variables. So for example, if the variables are submitted in the FORM scope, the final query might look something like this. (Modify the cfsqltypes as needed.)
<cfquery datasource="#variables.dsn#">
INSERT INTO into log (
program_id
, paragraph_id
, userid
, action
, paragraph_text_old
, paragraph_text_new
)
VALUES
(
<cfqueryparam value="#FORM.program_id#" cfsqltype="CF_SQL_INTEGER">
, <cfqueryparam value="#FORM.paragraph_id#" cfsqltype="CF_SQL_INTEGER" null="#NOT IsNumeric(FORM.paragraph_id)#">
, <cfqueryparam value="#Session.userid#" cfsqltype="CF_SQL_INTEGER">
, 'Paragraph Updated'
, <cfqueryparam cfsqltype="CF_SQL_CLOB" value="#rs_d.paragraph_text#">
, <cfqueryparam cfsqltype="CF_SQL_CLOB" value="#FORM.input#">
)
</cfquery>
NB: Unless a column has a different default value assigned, NULL will be inserted automatically when that column is omitted from the INSERT list.
I suggest re-arranging your logic to determine field null variables which then get used in the null attribute of cfqueryparam. Something like this:
<cfscript>
fieldOneNull = conditionForNull ? true : false;
fieldTwoNull = conditionForNull ? true : false;
etc
</cfscript>
<cfquery>
insert into table
(field1, field2, etc)
values
(
<cfqueryparam cfsqltype="cf_sql_whatever" value="something" null="#fieldOneNull#">
, <cfqueryparam cfsqltype="cf_sql_whatever" value="something" null="#fieldTwoNull#">
, etc
)
Thanks for the suggestions. Instead of modifying the existing function which is used in different areas of the application, I added a new insert statement in the position where the function was being called to deal with the clobs. To deal with the null fields I used a case statement.
<cfquery datasource="#dsn#">
insert into log (
LOG_ENTRY_ID, program_id, paragraph_id, userid, action, paragraph_text_old
, paragraph_text_new, comment_id, current_program_status, new_program_status
)
values (
null ,#program_id#,(case when #paragraph_id# = '' then null else #paragraph_id# end)
, #Session.userid# , 'Paragraph Updated'
, <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#rs_d.paragraph_text#>
, <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#input#>
, null, null , null
)
</cfquery>
Related
I have simple multiple insert:
$query = "
INSERT INTO `products` SET `code` = '0100130', `price` = '273.90', `brand` = 'Alpina', `supplier` = 'karat';
INSERT INTO `products` SET `code` = '0600075', `price` = '222.24', `brand` = 'Alpina', `supplier` = 'karat';
";
I have tried DB::raw($query), DB::query($query), DB::statement($query) - all three fails. But all three works if there is only one INSERT statement. If more than one, I get no error, but inserts are not performed.
I'm looking for a fastest way to import 13million inserts. Inserting one by one will take 24 hours for server.
Laravel v7.12.0
Try like this :
$query = "
INSERT INTO products(code, price, brand, supplier) VALUES
(0100130, 273.90, 'Alpina', 'karat'),
(0100130, 273.90, 'Alpina', 'karat')
";
You can't do two (or more) INSERT INTO into one sql query.
I have the following code:
#RegisterMapper(MyEntity.ResultMapper.class)
#UseStringTemplate3StatementLocator
public interface MyDao {
#Transaction(TransactionIsolationLevel.SERIALIZABLE)
#SqlBatch("INSERT INTO mySchema.myTable (" +
" id, entity_type, entity_id, flags " +
" ) VALUES " +
"(" +
" :stepId , :entityType , :entityId,parse_json(:flags) " +
")")
#BatchChunkSize(500)
Object create( #BindBean List<MyEntity> entities );
}
As you can see, I am bulk inserting a list of entities into my Snowflake table using this DAO.
The issue is that I am unable to insert into the flags columns, which is a variant. I have tried to_variant(:flags) and currently parse_json(:flags), but the JDBI keeps throwing the following error:
net.snowflake.client.jdbc.SnowflakeSQLException: SQL
compilation error:
Invalid expression [PARSE_JSON(?)] in VALUES clause
[statement:"INSERT INTO mySchema.myTable ( id, entity_type,
entity_id, flags ) VALUES ( :stepId , :entityType , :entityId,
parse_json(:flags) )", located:"null", rewritten:"null",
arguments:{ positional:{}, named:{timeStamp:'null',
entityType:MYENTITY,
flags:'{"client":"myClient","flow":"myFlow"}',stepId:null,
entityId:'189643357241513', class:class myOrg.MyEntity}, finder:[]}]
How should I pass the value in the flags column ? Has anyone attempted this before? The flags field in MyEntity is in my control, I can keep it as a POJO or a String, whichever helps me resolve this issue.
See the comment by Jiansheng Huang for answer:
INSERT INTO T SELECT parse_json(:flag);
I want to be able to let the business manually enter a USERID into a parameter box or leave it blank for it to bring back all USERID's.
I have setup another parameter for CUSTOMERID which uses a dataset to bring back a list of customer ID's. Due to the amount of USERID's I don't want to use the same solution but instead have them manually enter the USERID or leave it blank and bring back ALL.
SELECT
CUSTOMERID,
CASE
WHEN STATUSCODE = 200 THEN 'Successful Logon'
ELSE 'Unsuccessful Logon'
END as LogonStatus,
COUNT( * ) COUNTOFACCOUNTS
FROM
MA4EQNG.APPLICATIONLOG
WHERE
CUSTOMERID in ('"+join(Parameters!CustomerID.Value, "','")+"')
AND (Cast(DATETIME as Date) >= '"& Format(Parameters!FromDate.Value, "yyyy-MM-dd") & "'
AND Cast(DATETIME as Date) <= '" & Format(Parameters!ToDate.Value, "yyyy-MM-dd") & "')
AND COMPONENTDESCRIPTION = '/eq/auth/v1/logon'
AND METHOD = 'POST'
GROUP BY
CUSTOMERID,
CASE
WHEN STATUSCODE = 200 THEN 'Successful Logon'
ELSE 'Unsuccessful Logon'
END
ORDER BY
CUSTOMERID ASC
Please let me know if you need anything else.
You can set the USERID parameter to allow blank value then use IF condition on your main dataset sql script.
Try
IF LEN(#USERID)>0
*put the sql script with UserId filter in where clause*
ELSE
*put the sql script WITHOUT UserId filter in where clause*
Normally you would just script something like this in the WHERE clause.
WHERE
isnull(#CustomerID,'') = '' OR (CUSTOMERID in('"+join(Parameters!CustomerID.Value, "','")+"'))
And long term, I would create a function that takes in a delimited string, and converts them to rows, then you can just join on the results from the table valued function.
How to split a comma-separated value to columns
sql = "update Attendance set Attended=Attended+1 where Student ID like 15001"
db.Execute (sql)
is is showing :
"syntax error(missing operator) in query expression 'Student ID like
15001'
If realy you have a space between Student and ID tehn your query must be :
sql = "update Attendance set Attended=Attended+1 where [Student ID] like 15001"
db.Execute (sql)
sql should always be written with an _. For Example Student ID should always be Student_ID so that it has the idea of reading which column it needs to filter its search. For future purposes always create a column name with an _.
sql = "update Attendance set Attended=Attended+1 where Student_ID like 15001"
db.Execute (sql)
or
sql = "update Attendance set Attended=Attended+1 where [Student ID] like 15001"
db.Execute (sql)
Try something that looks a bit cleaner...
sql = "Update tblAttendance SET "
sql = sql & " Attended = Attended + 1 "
sql = sql & " Where Student_ID = 15001 "
db.execute SQL <-- no paranthesis
I'm using an Access over Oracle database system (Basically using Access for the forms and getting into the tables using ADO code) and am trying to update a field in the product table with the value of the same named field in a load table.
The code I am using is:
.CommandText = "UPDATE " & strSchema & ".TBL_CAPITAL_MGMT_PRODUCT a INNER JOIN " & strSchema & ".TBL_CAPITAL_MGMT_TEMP_LOAD b ON a.AR_ID = b.AR_ID SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;"
Which returns an error about missing SET keyword.. So I changed it to:
.CommandText = "UPDATE (SELECT a.TOT_RWA_AMT, b.TOT_RWA_AMT As New_RWA_AMT FROM " & strSchema & ".TBL_CAPITAL_MGMT_TEMP_LOAD a INNER JOIN " & strSchema & ".TBL_CAPITAL_MGMT_PRODUCT b ON b.AR_ID = a.AR_ID Where a.New_Rec <> '-1' AND a.IP_ID Is Not Null) c SET c.New_RWA_AMT = c.TOT_RWA_AMT;"
Which returns an error about non key-preserved table. the b table has a pk of AR_ID but the a table has no primary key and it probably won't be getting one, I can't update the structure of any of the tables.
I tried using the /*+ BYPASS_UJVC */ which lets the code run, but doesn't actually seem to do anything.
Anyone got any ideas where I should go from here?
Thanks
Alex
Ignoring the irrelevant ADO code, the update you are trying to do is:
UPDATE TBL_CAPITAL_MGMT_PRODUCT a
INNER JOIN
SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;
This isn't supported by Oracle (though maybe this undocumented BYPASS_UJVC hint is supposed to overcome that, but I wasn't aware of it till now).
Given that your inline view version fails due to lack of constraints you may have to fall back on the traditional Oracle approach using correlated subqueries:
UPDATE TBL_CAPITAL_MGMT_PRODUCT a
SET a.TOT_RWA_AMT = (SELECT b.TOT_RWA_AMT
FROM TBL_CAPITAL_MGMT_TEMP_LOAD b
WHERE a.AR_ID = b.AR_ID
)
WHERE EXISTS (SELECT NULL
FROM TBL_CAPITAL_MGMT_TEMP_LOAD b
WHERE a.AR_ID = b.AR_ID
);
The final WHERE clause is to prevent TOT_RWA_AMT being set to NULL on any "a" rows that don't have a matching "b" row. If you know that can never happen you can remove the WHERE clause.
If you're using Oracle 10g or higher, an alternative to Tony's solution would be to use a MERGE statement with only a MATCHED clause.
MERGE INTO TBL_CAPITAL_MGMT_PRODUCT a
USING TBL_CAPITAL_MGMT_TEMP_LOAD b
ON (a.AR_ID = b.AR_ID)
WHEN MATCHED THEN
UPDATE SET a.TOT_RWA_AMT = b.TOT_RWA_AMT;