Good Day all,
I am writing a program to build a report where I build the SQL statement to insert selected records into a file and after that insert I would like to do a simple update on the file to change a select fields in some records.
The problem is that after the insert is run, anytime I try to update the file I get a Record or File in use error.
I have tried updating it programatically with sqlrpgle and with I/O read and set functions and I have even tried just updating the file in STRSQL after I run the program and I all come to the same error.
I suspect I am not closing something properly but I am not sure what.
Code is as follows
// Assign SQL Query
sqlstmt = 'insert into jallib/orhsrpt ('+
'oacctd, oacmp, oaord, oacust, o8type, ' +
'o8text, o8date, o8time ) ' +
'select oacctd, oacmp, oaord, oacust, ' +
'o8type, o8text, o8date, o8time ' +
'from r50files.vcohead ' +
'join r50files.vcopkct ' +
'on oacmp = o8cmp and oaord = o8ord ' +
'where oacmp = 1 ' +
'and o8type not in (' +
'''C'',''a'',''H'',''E'',''F'', '+
'''A'',''1'',''N'',''M'') ' +
'and oacctd = ' + curdate +
' order by oaord, o8time ';
// Prepare for multiple sql statements
exec sql
Set Option Commit = *NONE;
// Clear output file before executing SQL
exec sql
Delete from jallib/orhsrpt;
if sqlcode < *zeros;
errmsg = 'Delete of file failed';
endif;
// Execute SQL Insert statement
exec sql prepare sqlsel from :sqlstmt;
exec sql execute sqlsel;
if sqlcode < *zeros;
errmsg = 'Insert of file failed';
endif;
// Update file data
exec sql
Set Option clossqlcsr = *ENDMOD;
exec sql
Update jallib/orhsrpt
set o8text = 'Order Invoiced'
where o8type = 'I'
The error from STRSQL is as follows
Row or object ORHSRPT in JALLIB type *FILE in use.
The quick answer is that the insert is not closed because your module hasn't ended according to the Set Option you specified. However, the correct answer here is that there is no reason for you to be using dynamic SQL statements at all. They are slower and more error prone in general and you run into issues like this one. You should instead use a regular embedded SQL statement as below:
exec sql
set option commit = *NONE;
// Clear output file before executing SQL
exec sql
delete from jallib/orhsrpt;
if sqlstate <> *zeros;
errmsg = 'Delete of file failed';
endif;
exec sql
insert into jallib/orhsrpt (
oacctd, oacmp, oaord, oacust,
o8type, o8text, o8date, o8time )
select oacctd, oacmp, oaord, oacust, o8type,
o8text, o8date, o8time
from r50files.vcohead join r50files.vcopkct
on oacmp = o8cmp and oaord = o8ord
where oacmp = 1 and o8type not in (
'C','a','H','E','F', 'A','1','N','M') and
oacctd = :curdate
order by oaord, o8time;
exec sql
update jallib/orhsrpt
set o8text = 'Order Invoiced'
where o8type = 'I'
This is better practice and should solve your issue.
Related
how can I make Code A dynamic using Execute SQL Task in SSIS?
Code A
SELECT SUM(DuplicateCount) AS TotalRow
FROM (
SELECT COUNT(ID + CheckCode) AS DuplicateCount
FROM Tbl_CheckCode
GROUP BY ID, CheckCode
HAVING COUNT(ID + CheckCode) > 1
) AS U
I've tried on storing the code in an object variable so I could use it as follows.
Code B
SELECT SUM(DuplicateCount) AS TotalRow
FROM (?) AS U
However, seems like SSIS is not allowing this. Any ideas?
Use another variable to create your entire SQL statement, and use that in the Execute SQL Task.
#CodeAVar = 'SELECT SUM(DuplicateCount) AS TotalRow
FROM (' + #CodeBVar + ') AS U'
I've figured it out.
Under the expressions section of the Execute SQL Task Editor, I've set the following code as the SQLStatementSource:
"SELECT SUM(DuplicateCount) AS TotalRow
FROM (" + #[User::SQLQuery] + ") AS U"
And automatically, it generated the following code in SQLStatement under the General section:
SELECT SUM(DuplicateCount) AS TotalRow
FROM () AS U
I've met the problem when using execute immediate in Teradata.
SET str_sql = 'UPDATE TABLE
SET COLA = 0';
EXECUTE IMMEDIATE str_sql;
The above code works fine.
SET str_sql = 'UPDATE TABLE
SET COLA = 0,
COLB = ''test''';
EXECUTE IMMEDIATE str_sql;
The above code with string returns error.
The following is the error message:
Executed as Single statement. Failed [3706 : 42000] Table:Syntax error: expected something between a string or a Unicode character literal and the word 'test'.
Elapsed time = 00:00:00.212
STATEMENT 1: CALL failed.
Anyone know how to invoke the execute immediate with String in the sql?
Thanks!
Frank Liu
The problem might be on quotation. Instead of this
SET str_sql = 'UPDATE TABLE
SET COLA = 0,
COLB = ''test''';
EXECUTE IMMEDIATE str_sql;
Use double quotation.
SET str_sql = 'UPDATE TABLE
SET COLA = 0,
COLB = 'test'';
EXECUTE IMMEDIATE str_sql;
I am working on a FILE that I need to move from one loacation to another, but when I run the code below I keep getting an error that it has the incorrect syntax. When I print the #Move statement I get this: (Which is what I think I should get)
MOVE \appdev1\sqltest\RedFlag\RedFlag Address Change New Debit Issued.pdf \appdev1\sqltest\RedFlag\2013-10-24_REDFLAG_.pdf
I am trying to run it like this:
EXEC MASTER.DBO.XP_CMDSHELL #MOVE
Any suggestions on what I am doing wrong? Do I need to add the ' in front of the Move statement?
You have spaces in your paths/filenames, so you need to surround with double quotes.
SET #MOVE = 'MOVE "\\appdev1\... Issued.pdf" "\\appdev1\..._.pdf"';
If you are constructing a path from variables, this doesn't change anything. Staying in T-SQL, you would have parameters like this I presume:
SET #MOVE = 'MOVE "' + #OldFile + '" "' + #Printed + '"';
You'll have to work it out yourself if you are doing this in some other language. Here is a short demonstration of how it works in T-SQL:
DECLARE #MOVE VARCHAR(255),
#OldFile VARCHAR(255) = '\\foo\some filename.pdf',
#Printed VARCHAR(244) = '\\blat\something else.pdf';
SET #MOVE = 'MOVE "' + #OldFile + '" "' + #Printed + '"';
PRINT #MOVE;
Results:
MOVE "\\foo\some filename.pdf" "\\blat\something else.pdf"
I don't see any extra quotes, so maybe those are coming from whatever value you have in your parameters.
The following queries update the same table like 7 times.. I would appreciate your help on how I might optimize this by putting it into one query so it passes through the table only once instead of 7 times.. This is really slowing down performance on large datasets..
Thanks.
P.S. I don't know if it will still work out but each query string depends on the query before it to accurately calculate.. So if we need to keep them separate in order to keep it accurate then I could use some help optimizing each string (query) individually.
The following SQL queries are made in Delphi 2009 So the format may be a little different but you should still be able to read the query pretty easily..
Str1 :=
'update user set amount = ' +
'(select round(sum(bill.amount),2) from bill where ' +
'bill.user = user.code); ' +
'update user set pay = ' +
'(select round(sum(bill.pay),2) from bill where ' +
'bill.user = user.code); ' +
'update user set balance = round(amount + pay,2);';
//execute query
Str1 :=
'update user set group_amt = ' +
'(select sum(bill.amount) from bill where ' +
'bill.client = user.client); ' +
'update user set group_pay = ' +
'(select sum(bill.pay) from bill where ' +
'bill.client = user.client); ' +
'update user set group_bal = round(group_amt + group_pay,2);';
//execute query
Str1 :=
'update user set bal_flag = true ' +
'where abs(balance) > 0.001 and bal_flag = false;';
I suspect you can merge 6 of the updates into just 2 updates...
UPDATE
user
SET
amount = bill.amount,
pay = bill.pay,
balance = bill.pay + bill.amount
FROM
(
SELECT
user,
round(sum(bill.amount),2) AS amount,
round(sum(bill.pay) ,2) AS pay
FROM
bill
GROUP BY
user
)
AS bill
WHERE
bill.user = user.code
And nearly identically...
UPDATE
user
SET
group_amt = bill.amount,
group_pay = bill.pay,
group_bal = bill.pay + bill.amount
FROM
(
SELECT
client,
round(sum(bill.amount),2) AS amount,
round(sum(bill.pay) ,2) AS pay
FROM
bill
GROUP BY
client
)
AS bill
WHERE
bill.client = user.client
Assume that we have this SQL statement:
UPDATE article SET saison='12E', mode='ECH', client='SAS', WHERE ID='3448fe81-1bec-e011-8546-001f3ccf8f20'
This SQL statement is generated by concatenated strings like this:
// saison change
procedure TarticleEditForm.saisonComboChange(Sender: TObject);
begin
SQLQuery := SQLQuery + 'saison=''' + saisonCombo.Text + ''',';
end;
// client change
procedure TarticleEditForm.clientComboChange(Sender: TObject);
begin
SQLQuery := SQLQuery + 'client=''' + clientCombo.Text + ''',';
end;
.
.
.
As you see, there is a comma before "WHERE" clause. How can I remove the last comma to have the correct statement:
UPDATE article SET saison='12E', mode='ECH', client='SAS' WHERE ID='3448fe81-1bec-e011-8546-001f3ccf8f20'
RMQ: the number of comma is not fixe, it can be 1, 2, 5...
thank you.
The solution is replacing ", WHERE" by "WHERE"
SQLQuery := StringReplace(SQLQuery , ', WHERE', 'WHERE', [rfReplaceAll]);
I am using this to trace every change in HISTORY Table.
Thank you all.
Rather than concatenating the changes to the SQL string as they happen, store them in a collection and build you SQL string after all the options have been evaluated.
Then you will know how many fields are going to be changed and build the statement correctly. Of course this will require you to store not only the value but also the name of the fild being changed:
[pseudo code]
for i=0 to fields_changed.count {
sql = sql + fields_changed(i).field_name + " = " + fields_changed(i).new_value
if i < fields_changed.count {
sql = sql + ", "
}
}
sql = sql + " WHERE ..."
EDIT: The other option you have is to simply perform a string replace on , WHERE with WHERE just before executing the statement; since the word 'where' is a reserved word and should not occur more than once in your SQL statement. This may be the simpler solution even if it feels like a bit of a hack.
another option is to reduce the length of the string by 1 character before appending the WHERE clause.