I have a table fepu00 and trigger on it.
The part of code causing tha problem looks like follows:
if (old_record.potime = NEW.putime --new AP (read in statement above)
or old_record.pupisb::NUMERIC != NEW.pupisb::NUMERIC) then
insert into dl356_table
values (old_record.poid, old_record.poidma, old_record.ponmaf,
old_record.adstr, old_record.adpsc, old_record.adcit, old_record.adidze,
NEW.pupisb::numeric,
case when old_record.potime = NEW.putime then '1' else '2' end,
NEW.putime);
end if;
The query I'm executing is really simple:
update fepu00 set pudas = ? where puid = ?
It works, but only for some quantity of times. Then it throws:
ERROR: type of parameter 25 (numeric) does not match that when preparing the plan (text)
Where: PL/pgSQL function dl356_trigger() line 75 at IF
Number of updated records varies from a few to a few hundreds.
When I run the same query (with the same parameters) again, it works properly until the next fail.
Thanks for any suggestions.
I have a SQL query which takes user inputs hence security flaw is present.
The existing query is:
SELECT BUS_NM, STR_ADDR_1, CITY_NM, STATE_CD, POSTAL_CD, COUNTRY_CD,
BUS_PHONE_NB,PEG_ACCOUNT_ID, GDN_ALERT_ID, GBIN, GDN_MON_REF_NB,
ALERT_DT, ALERT_TYPE, ALERT_DESC,ALERT_PRIORITY
FROM ( SELECT A.BUS_NM, AE.STR_ADDR_1, A.CITY_NM, A.STATE_CD, A.POSTAL_CD,
CC.COUNTRY_CD, A.BUS_PHONE_NB, A.PEG_ACCOUNT_ID, 'I' ||
LPAD(INTL_ALERT_DTL_ID, 9,'0') GDN_ALERT_ID,
LPAD(IA.GBIN, 9,'0') GBIN, IA.GDN_MON_REF_NB,
DATE(IAD.ALERT_TS) ALERT_DT,
XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing
IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE,
, ROW_NUMBER() OVER () AS "RN"
FROM ACCOUNT A, Other tables
WHERE IA.GDN_MON_REF_NB = '100'
AND A.PEG_ACCOUNT_ID = IAAR.PEG_ACCOUNT_ID
AND CC.COUNTRY_CD = A.COUNTRY_ISO3_CD
ORDER BY IA.INTL_ALERT_ID ASC )
WHERE ALERT_TYPE IN (" +TriggerType+ ");
I changed it to accept TriggerType from setString like:
SELECT BUS_NM, STR_ADDR_1, CITY_NM, STATE_CD, POSTAL_CD, COUNTRY_CD,
BUS_PHONE_NB,PEG_ACCOUNT_ID, GDN_ALERT_ID, GBIN, GDN_MON_REF_NB,
ALERT_DT, ALERT_TYPE, ALERT_DESC,ALERT_PRIORITY
FROM ( SELECT A.BUS_NM, AE.STR_ADDR_1, A.CITY_NM, A.STATE_CD, A.POSTAL_CD,
CC.COUNTRY_CD, A.BUS_PHONE_NB, A.PEG_ACCOUNT_ID,
'I' || LPAD(INTL_ALERT_DTL_ID, 9,'0') GDN_ALERT_ID,
LPAD(IA.GBIN, 9,'0') GBIN, IA.GDN_MON_REF_NB,
DATE(IAD.ALERT_TS) ALERT_DT,
XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing
IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE,
ROW_NUMBER() OVER () AS "RN"
FROM ACCOUNT A, other tables
WHERE IA.GDN_MON_REF_NB = '100'
AND A.PEG_ACCOUNT_ID = IAAR.PEG_ACCOUNT_ID
AND CC.COUNTRY_CD = A.COUNTRY_ISO3_CD
ORDER BY IA.INTL_ALERT_ID ASC )
WHERE ALERT_TYPE IN (?);
Setting trigger type as below:
if (StringUtils.isNotBlank(request.getTriggerType())) {
preparedStatement.setString(1, triggerType != null ? triggerType.toString() : "");
}
Getting error as
Caused by: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=4.19.26
The -302 SQLCODE indicates a conversion error of some sort.
SQLSTATE 22001 narrows that down a bit by telling us that you are trying to force a big string into a small variable. Given the limited information in your question, I am guessing it is the XMLCAST that is the culprit.
DB2 won't jam 30 pounds of crap into a 4 pound bag so to speak, it gives you an error. Maybe giving XML some extra room in the cast might be a help. If you need to make sure it ends up being only 4 characters long, you could explicitly do a LEFT(XMLCAST( ... AS VARCHAR(64)), 4). That way the XMLCAST has the space it needs, but you cut it back to fit your variable on the fetch.
The other thing could be that the variable being passed to the parameter marker is too long. DB2 will guess the type and length based on the length of ALERT_TYPE. Note that you can only pass a single value through a parameter marker. If you pass a comma separated list, it will not behave as expected (unless you expect ALERT_TYPE to also contain a comma separated list). If you are getting the comma separated list from a table, you can use a sub-select instead.
Wrong IN predicate use with a parameter.
Do not expect that IN ('AAAA, M250, ABCD') (as you try to do passing a comma-separated string as a single parameter) works as IN ('AAAA', 'M250', 'ABCD') (as you need). These predicates are not equivalent.
You need some "string tokenizer", if you want to pass such a comma-separated string like below.
select t.*
from
(
select XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE
from table(values xmlparse(document '<alertTypeConfig><biqCode>M250, really big code</biqCode></alertTypeConfig>')) IAC(INTL_ALERT_TYPE_CONFIG)
) t
--WHERE ALERT_TYPE IN ('AAAA, M250, ABCD')
join xmltable('for $id in tokenize($s, ",\s?") return <i>{string($id)}</i>'
passing cast('AAA, M250 , ABCD' as varchar(200)) as "s"
columns token varchar(200) path '.') x on x.token=t.ALERT_TYPE
;
Run the statement as is. Then you may uncomment the string with WHERE clause and comment out the rest to see what you try to do.
P.S.:
The error you get is probably because you don't specify the data type of the parameter (you don't use something like IN (cast(? as varchar(xxx))), and db2 compiler assumes that its length is equal to the length of the ALERT_TYPE expression (4 bytes).
I'm using CASE expression to display "NamaAyah" or "NamaIbu" or "NamaWali", and if all of them is empty, the default value will display "ORTU-'NomorPokok' ".
But the default value not displayed, it just displays symbol "-" in my table. I think the value in ELSE statement not executed.
Postgre Version : PostgreSQL 9.4.15
This is my code
SELECT
"MahasiswaID" AS "PERSONID","NomorPokok" AS "KODE",
UPPER(CASE
WHEN "NamaAyah" <> '' THEN "NamaAyah"
WHEN "NamaIbu" <> '' THEN "NamaIbu"
WHEN "NamaWali" <> '' THEN "NamaWali"
ELSE 'ORTU'||'-'||"NomorPokok"
END) AS "NAMALENGKAP"
FROM "MasterMahasiswa" ORDER BY "KODE"
and this is the result
The expression you have can simpler be:
ELSE 'ORTU-'||"NomorPokok"
Apart from that, the only reasonable explanation for what you display is that there are literal - in one or more of your columns "NamaAyah", "NamaIbu" and "NamaWali". Did you check that?
I need to build a SQL statement to be submitted on a linked server. The statement makes use of #parameters and case statements which contain quotation marks.
I found this Microsoft article 'How to pass a variable', which seemed ideal, however I am not able to get everything going. It seems that the linked server is not enabled for the final and neatest suggestion of calling Sp_executesql, so I have been trying the first two examples.
To start with, here is a cut down example of my SQL statement on its own:
SELECT *,
CASE WHEN FLDA = 'ABC' THEN 'DEF' ELSE 'ABC' END AS COL1
FROM MYTABLE
WHERE FLDB = #PARM
1, I can get the query to work when excluding the CASE statement:
DECLARE #TSQL NVARCHAR(4000), #PARM NVARCHAR(10)
SET #PARM = 'ABC'
SET #TSQL = 'SELECT * FROM OPENQUERY(MYLINKEDSERVER, ''
SELECT *
FROM MYTABLE
WHERE FLDA = '''''+#PARM+''''''')'
EXEC (#TSQL)
However I don't understand why I require 5 quotes before #PARM and then 7(!) after it? When coding SQL statements in a string in previous languages just 2 quotations together acted as a single. So why 5 and 7?
2, I can't get the SQL to work at all when attempting to add the CASE statement. I have tried all combinations of 2,3,4 quotations but to no avail: Do I again need a certain amount of opening quotes and then a different amount of closing quotes?
DECLARE #TSQL NVARCHAR(4000), #PARM NVARCHAR(10)
SET #PARM = 'ABC'
SET #TSQL = 'SELECT * FROM OPENQUERY(MYLINKEDSERVER, ''
SELECT *,
CASE WHEN FLDA = ''ABC'' THEN ''DEF'' ELSE ''ABC'' END AS COL1
FROM MYTABLE
WHERE FLDA = '''''+#PARM+''''''')'
EXEC (#TSQL)
Any help greatly appreciated!
Cheers
Mark
my first question was why do I need 5 and 7 quotes, so there was no error message there, but I get the point that I could have listed some of the errors seen when I was getting the incorrect number of quotes.
However the tip to use Print was very useful, so thank you all for that!
So it transpires that I do indeed require a pair of
quotes where a single quote is required. However, as I am creating a SQL string within a string, I need to double that again. So I first need to end my string with a single quote and then add 4 quotes to create the double quote required to proceed the variable - hence 5. And likewise, I need 4 quotes to get a pair of quotes following the variable, another pair of quotes for the quote to end the statement and then a final one to wrap around the end bracket of the OPENQUERY command....I hope that sort of reads correct!
So:
WHERE FLDA = '''''+#PARM+''''''')'
Printed as:
WHERE FLDA = ''ABC''')
And for my CASE statement, I required 4 set of quotes, to equate to 2. So:
CASE WHEN FLDA = ''''ABC'''' THEN ''''DEF'''' ELSE ''''ABC'''' END AS COL1
Printed as:
CASE WHEN FLDA = ''ABC'' THEN ''DEF'' ELSE ''ABC'' END AS COL1
I'm doing a little application for the work and it includes a form. When the person using the form doesn't put a value in a data type "numeric" (lets say a PIN number) or even a date in one of my "date" Data Type fields (lets say his anniverssary), it returns me with the errors as follow:
Error Type – Type d'erreur
_Microsoft OLE DB Provider for ODBC Drivers (0x80004005)_
ERROR: invalid input syntax for type numeric: ""; Error while executing the query
Error Type – Type d'erreur
_Microsoft OLE DB Provider for ODBC Drivers (0x80004005)_
ERROR: syntax error at or near ")"; Error while executing the query
So it seems that when the person using the form enters nothing, it returns the string "empty" that is "".
Why can't the numeric type and data type read that as a NULL entry? These fields are not mandatory and so I need to have them be sometimes blank.
How can I make it possible? Is their a way to keep using "numeric" and "date" type so that when the user enters nothing in those fields, the table fills with a blank case insted of giving me this error?
Here is my sql statement :
trsConn.EXECUTE "INSERT INTO ""TRS"".employeetbl ( "& _
"""firstName"", " & _
"""lastName"" , " & _
"""detContract"", " & _
"sle, " & _
"""posNumber"" "& _
") VALUES (" & _
"'" & Request.Form("empFirst") & "', " & _**
"'" & Replace(Request.Form("empLast"), "'", "`") & "', " & _
"'" & Request.Form("dateContract") & "', " & _
"'" & Request.Form("sle") & "', " & _
"'" & Request.Form("posNum") & "');"
(The posNum and dateContract are both respectivly of type "numeric" and "date"
Thanks so much for the help. Looking forward for hearing what you geniuses have to say.
The concept of NULL in SQL is pretty muddled and inconsistent ... but it's very clear that '' is distinct from NULL.
'' isn't NULL, it's '', the empty string. You can't convert it to a date, number, etc:
regress=# SELECT CAST('' AS DATE);
ERROR: invalid input syntax for type date: ""
LINE 1: SELECT CAST('' AS DATE);
^
regress=# SELECT CAST('' AS NUMERIC);
ERROR: invalid input syntax for type numeric: ""
LINE 1: SELECT CAST('' AS NUMERIC);
^
Some products - notably Microsoft Access and old versions of MySQL - are confused about that matter. NULL is NULL, '' is the empty string; they aren't the same thing. You can't convert one to the other.
So it seems that when the person using the form enters nothing, it
returns the string "empty" that is "". Why can't the numeric type and
data type read that as a NULL entry? These fields are not mandatory
and so I need to have them be sometimes blank.
That's your application's job. When your app it sees the empty string come in on a form field for a numeric, date, or similar, it should send NULL to the database, not ''. That's normally a routine part of converting data from user input before it's supplied to the database. It is vital that you do such conversion; you should never just send values from the user straight to the database.
A quick search suggests that asp classic uses null or undefined as its null values; you should be able to pass them into your prepared statements when something is null.
The fact that you get a syntax error after the error about '' suggests that you're building your SQL statements as strings, not using prepared statements with placeholders. (Thanks JayC for the SO question ref). This is begging for SQL injection; in other words your application is critically insecure. Imagine what happens if the user enters the "date":
2012-01-01'); DROP SCHEMA public;--
and your app happily turns that into
INSERT INTO sometable (blah, blah, blah) VALUES (1, 2, DATE '2012-01-01'); DROP SCHEMA public;--');
The DROP SCHEMA then merrily executes and whoops, splat, there goes your database. That's just the dumbest, simplest kind of SQL injection attack too.