ORA-28562 data error truncation in oracle heterogenous? - database

I have created an Oracle heterogenous service to db2 using DG4ODBC.
try login using isql and select using this query
select *from workorder#maximo
I get a result set all of the data
but when I am login using sqlplus Oracle I get this error
this is my heterogenous init
and I try using HS_FDS_TRACE_LEVEL=DEBUG and get some column have a sql_null_value
This the sample of the log from debugging:
if any columns have null value then the data cannot be showing.
how I can show the data even though have a null value??
I am using Oracle 12c and db2 10.5

Try using:
HS_FDS_SQLLEN_INTERPRETATION = 32
(From Ocacle docs) This parameter is only valid for 64 bit platforms. ODBC standard specifies SQLLEN (of internal ODBC construct) being 64 bit on 64 bit platforms, but some ODBC driver managers and drivers violate this convention, and implement it as 32 bit. In order for the gateway to compensate their behavior, you need to specify HS_FDS_SQLLEN_INTERPRETATION=32 if you use these types of driver managers and driver.
It is unclear from your question the bitness of the Db2 odbc client, or whether the driver-manager or driver is using 32-bit or 64-bit internally for this. After changing this parameter you may need to re-initialise. A CLI trace of Db2 (google for instructions) may also expose this.

I've got this error when I was trying to load a TEXT data type from Postgres to Oracle VARCHAR2(4000) and the source data in the TEXT column was bigger than 4000 bytes.
One of available workarounds could be to map TEXT column to PL/SQL's VARCHAR2(32767) variable or maybe LONG, CLOB data type.

Related

Configure charset for ODBC Driver 17 for SQL Server

I'm running a Windows application on Linux under Wine, that accesses a SQL Server using the ODBC Driver 17 for SQL Server, for Linux.
It runs fine except that I see incorrectly represented the varchars with non-Ascii characters. The nvarchar fields (unicode strings) have no problem.
Example:
select rtrim('Presentación ')
Returns: Presentación
My database has the encoding for varchars defined as iso8859-1, and Wine seems to use the cp1252 page code.
My guess is that the ODBC driver for Linux retrieves correctly the data and transforms them to UTF8, which runs fine (I can see the values correctly if I run my queries directly through isql), but when those strings are passed to my application, under Wine, they must be considered as cp1252 and that's when I see them incorrectly.
Has anyone had the same problem? what could I try?
Thank you.

JDBC getNString()

I'm working with a Java web application backed by a Microsoft SQL Server. I have used nvarchar columns and my plan is to support Unicode characters. So in my JDBC layer I have used getNString() method from the result set and it works fine. However just for curiosity I changed all the getNString() methods to normal getString() methods and it also works fine displaying Unicode characters correctly.
I found the similar observation from below question as well
Should I be using JDBC getNString() instead of getString()?
Do you guys have any idea about this?
The presence of getNString and setNString is - in my opinion - a design mistake of JDBC. However, database systems that discern between (VAR)CHAR and N(VAR)CHAR can take this setter as a type hint to send the data in their specific format for N(VAR)CHAR. For getters there will usually be no difference as in most drivers, the data will have already been fetched before this method can be called, and a driver should know the proper conversion.
Specifically for the Microsoft SQL Server JDBC driver, with default configuration there is no difference between using setString or setNString: both will lead to the values being sent as unicode. This changes when the connection property sendStringParametersAsUnicode has been set to false.
See also NVARCHAR Support in Type 2 SQL Server 2008 JDBC Driver:
You do not need to use the JDBC 4 API to work with NVARCHAR (UCS-2)
data in SQL Server. Existing JDBC 3 APIs such as
getString/setString/updateString are used to get/set/update Unicode
values as Java Strings (which are always Unicode). The only thing to
be aware of when using the JDBC 3 methods is the setting of the
sendStringParametersAsUnicode property. This property is set to
'true' by default, which means that PreparedStatement and
CallableStatement parameters are sent to SQL Server in Unicode.
Changing the setting to 'false' allows the driver to save space in the
protocol by converting input parameter values to the character set of
the database when sending them.
That said, using the JDBC 4 API to work with NVARCHAR data has some
advantages. The main advantage is formal recognition of the NVARCHAR
type by the JDBC API, including accessor methods such as
getNString/setNString/updateNString. For example, the setNString
method can be used to send input parameter values to SQL Server in
Unicode, even if sendStringParametersAsUnicode is set to 'false'.
Put another way, with the default setting of
sendStringParametersAsUnicode=true, the JDBC 4 'N' methods behave the
same way as the JDBC 3/JDBC 4 non-'N' methods with respect to NVARCHAR
data.
For more information on the sendStringParametersAsUnicode connection property, see Setting the Connection Properties.

SSIS cannot convert between unicode and non-unicode

I've an SSIS package which works perfectly on various server but doesn't on 2 newly added server.
It uses OLEDB (64bit, I've certified that) to get data from an ORACLE DB from a table with 3 VARCHAR2 columns and upsert the rows to a SQL 2012 table with 3 nvarchar columns, with the same size.
The package was working flawlessly in all the servers we deployed it. We recently added 2 new servers, with hopefully (I personally checked the possible major culprit: ODAC, dtexec version, tns names ) the same software with the same versions but the package is not working anymore. It gives us the famous error:
Description: Column "C_CODE" cannot convert between unicode and non-unicode s
tring data types.
End Error
Error: 2016-08-26 08:33:26.20
Code: 0xC02020F6
Source: Upsert Lines OLE DB Source [87]
Description: Column "S_DESC" cannot convert between unicode and non-unicode s
tring data types.
End Error
Warning: 2016-08-26 08:33:26.20
Code: 0x800470C8
Source: Upsert Lines OLE DB Source [87]
Description: The external columns for OLE DB Source are out of synchronizatio
n with the data source columns. The external column "C_CODE" needs to be updated
.
The external column "S_DESC" needs to be updated.
End Warning
The first warning I got was the "Cannot read the code page from Oracle server" so I tried to put the "use the default one every time" in combination with ANSI or UTF-8 code pages ( used this website to get the codepages: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx ).
The only way I made it work was to manually modify the OLE DB Source block into the package by changing the external columns to ansi strings, making it not compilable in the dev environment, then put a data transform that would change the exernal columns to utf-8 string again.
This way it doesn't work in the other servers but does flawlessly in the "faulty" servers.
I was thinking that the fact the package cannot read the code page from Oracle server is the culprit but I couldn't figure out how to fix it.
The problem is not like the million of questions about this issue you can find anywhere. The error being given is from the OLE DB Source block. I know about the data conversion.
Thanks in advance
The issue was the NLS_LANG registry key's value, it was set to an incorrect value.
I solved by deleting the said key, all worked fine.
Just come across this post (and many others about this issue) and believe I have found the underlying cause. On my servers at least, the 64bit version of the Windows Oracle drivers has a bug in the install process. I have checked the 32bit version and this bug is not there which explains the behaviour.
It appears that the 64bit version creates the NLS_LANG registry key in the wrong location. By default the 64bit driver create it here - "HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE"
I manually created it here - "HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient12Home1" which cured my issue. For reference my NLS_LANG key is set to "ENGLISH_UNITED KINGDOM.WE8MSWIN1252". I just created it as a copy of the string in the branch above.
I hope this helps others.
We use 32 bit SSIS with Oracle instant client, I need to add entry in this registration location
"Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ORACLE\KEY_OraClient12Home1_32bit"
The “NLS_LANG” value is “AMERICAN_AMERICA.WE8MSWIN1252”. This solved my problem.

DBMS_CRYPTO.RANDOMBYTES returns null

This statement returns null instead of 64 random bytes:
select DBMS_CRYPTO.RANDOMBYTES(64) from dual;
What is causing it to return null? Database is Oracle 10.1.0.2.0 running on Windows Server 2003 and I want to use the random bytes as salt for password hashing.
Edit: Here's the output from sqlplus:
Connected to:
Oracle Database 10g Release 10.1.0.2.0 - Production
SQL> select DBMS_CRYPTO.RANDOMBYTES(64) from dual;
DBMS_CRYPTO.RANDOMBYTES(64)
--------------------------------------------------------------------------------
SQL>
Edit2: When switching to Oracle 11 the query works. I have no idea why it doesn't work on Oracle 10 but have decided to not use that old database.
It works perfectly. I have tested it on Oracle 12c.
Update
I have checked My Oracle Support(Metalink), however, did not find anything related to this function returning NULL. Certainly, not a bug.
Anyway, looking deeper into the function and it's usage in the documentation, I came across SQLNET.CRYPTO_SEED
SQLNET.CRYPTO_SEED
Purpose
Use the parameter SQLNET.CRYPTO_SEED to specify the characters used
when generating cryptographic keys. The more random the characters
are, the stronger the keys are. The string should be 10-70 random
characters. This optional parameter is required for when encryption or
checksumming are turned on. Encryption is turned on if the
SQLNET.ENCRYPTION_CLIENT parameter is specified for the client and the
SQLNET.ENCRYPTION_SERVER parameter is specified for the database
server; checksumming is turned on if the SQLNET.CRYPTO_CHECKSUM_CLIENT
parameter is specified for the client and the
SQLNET.CRYPTO_CHECKSUM_SERVER parameter is specified for the database
server.
It might be possible that the parameter is not properly set in your environment. I don't have 10g version(obsolete though) to test.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing option
SQL> select DBMS_CRYPTO.RANDOMBYTES(64) from dual;
DBMS_CRYPTO.RANDOMBYTES(64)
--------------------------------------------------------------------------------
427AECD44D27CDF6CDC8F290D9F8079109BAB8AECD7E687E7ADF8E15825BBDF3D746FBC181059443
965B1425B224CC46E8CD07CC2D02B2E023238E8883520A19
SQL>

"String data, right truncation" warning on a select statement

I am upscaling an access 2003 database to SQL Server Express 2008. The tables appear to be created ok and the data looks ok.
I have an MFC application that connects to this database. It worked fine connecting to access, but when I connect to SQL Server I am getting the following error on a select statement.
DBMS: Microsoft SQL Server
Version: 10.50.1600
ODBC Driver Manager Version: 03.80.0000
Warning: ODBC Success With Info on field 0.
String data, right truncation
State:01004,Native:0,Origin:[Microsoft][ODBC SQL Server Driver]
The data that is returned should be 8 characters but is only 7 with the right most character truncated.
The access front end can read the data from SQL Server correctly.
The field in the SQL Server table is defined as nvarchar with a length of 8.
The code to read the field looks something like
CDatabase Database;
CString sSerialNumber = "00000000";
CString SqlString;
CString sDsn = "Driver={SQL Server};Server=server\\db;Database=Boards;Uid=uid;Pwd=pwd;Trusted_Connection=False";
Database.Open(NULL,false,false,sDsn);
CRecordset recset( &Database );
SqlString.Format("Select SerialNumber from boards where MACAddress = '%s'",mac);
recset.Open(CRecordset::forwardOnly,SqlString,CRecordset::readOnly);
recset.GetFieldValue("SerialNumber",sSerialNumber);
After this, sSerialNumber should be 12345678 but its 1234567
Thanks for the help
I'd agree that this is driver related. The {SQL Server} driver was introduced for use with SQL 2000. {SQL Native Client} came along with 2005. Ideally, for your 2008 database, you should use the newest {SQL Server Native Client 10.0}. The newer drivers are backward compatible with older versions of SQL Server.
Changing my driver from
"Driver={SQL Server};"
to
Driver={SQL Native Client};
has made the problem go away, but I'm not sure what was going on. I'm going to keep looking into it
From a bit of Googling, I've learned that apparently, at times, particularly when "Use Regional Settings" is checked in the MS SQL Server ODBC driver DSN setup dialog, ODBC will treat a string made up of all digits, as a number, and return it like "12345678.00" which doesn't fit into the space you've given it. The solution is to turn that setting off, either in the dialog box, or, more permanently, in the connection string:
CString sDsn = "Driver={SQL Server};Server=server\\db;Database=Boards;"
+"Uid=uid;Pwd=pwd;Trusted_Connection=False;Regional=No;"
If you absolutely have to dig to the bottom of this, make a minimal stored procedure that will "select" local var defined as varchar(17) - any size more than 2x your original size will do. Now call the sproc instead of dynamic SQL and see what comes back. Then you can repeat it with exactly the same size (nvarchar(8)). Your little sproc serves as easy data adapter and to stabilize typing if old driver tends to get confused - much easier than fiddling with table definition.
Also, check if there's any param/property on inreface/connection classes to specify character encoding and make sure that it's unicode (utf-16). I assume that your code gets compiled for unicode. If not, you need to make decision about that first (N in Nvarchar means unicode, otherwise it would be just varchar). You definitely need character encoding matched at both sides or you will have other spurious errors.

Resources