How to read SQL Server column collation metadata using ODBC API? - c++

Our C++ application is able to get collation related column metadata from SQL Server using OLEDB API’s (using DBCOLUMN_COLLATINGSEQUENCE, DBCOLUMN_TDSCOLLATION, etc.), but I need to use ODBC as our application has to be cross platform. We are using ODBC API SQLColAttribute to read rowset metadata, but this API does not have any identifiers which can return the collation name.
I tried using SQL_CA_SS_COLUMN_COLLATION (defined in sqlncli.h) as an identifier, but SQLColAttribute only returns “Collation Name” as the collation.
I also tried using SQLGetStmtAttr followed by SQLGetDescField, using the same identifier, and I got "Collation Name" back.
I have scoured all of MSDN for answers, but haven’t been able to find any. I can get the collation name from INFORMATION_SCHEMA.COLUMNS, but that will not work for calculated columns returned by queries.
I am looking for a clean way to get collation information from result set metadata using ODBC. Any ideas?

This query will return the collation_name for each column present in the current database.
SELECT o.name AS ObjectName, c.name AS ColumnName, c.collation_name
FROM sys.columns c
INNER JOIN sys.objects o ON c.object_id = o.object_id
INNER JOIN sys.types ty ON c.system_type_id = ty.system_type_id
WHERE o.is_ms_shipped = 0
AND ty.collation_name IS NOT NULL
AND ty.name <> 'sysname';

Related

wrong character showing when insert persian string to sql server using poco ODBC

I am trying to insert Persian string like "سلام" to SQL server 12 database with Poco ODBC. But in the database I see Characters like this "ط³ظ„ط§ظ…". the column data type is varchar(I try it with nvarchar too) and I test it with different Collation like Arabic_CI_AS and Persian_100_CI_AS.
there is no problem with data stored in the database. it is what I inserted into the database.
but when I try to see my database with Microsoft SQL Server Management Studio and another application with Qt interface, both of them show me "ط³ظ„ط§ظ…".
Does anyone have any idea how to fix it?
std::string updated = "سلام";
Statement select(session);
select << "INSERT INTO Employee VALUES( ?)",
use(updated),now;
Please change 'سلام' to N'سلام'

ODBC SQL Server Unicode Bug?

Background:
We have an application that uses the ODBC API to interact with Access and SQL Server (dynamically, depending on user's configuration).
I have discovered a bug which might be in the ODBC SQL driver, or may be a misconfiguration issue with the ODBC DSN we create, or may be a bug somehow in our code.
When a document is edited and saved, we query the database to see if this file has a corresponding record in the database - if so, we update the record with the updated data from the document; if not, we do an insert to create the necessary record for it.
We use the filename as the unique primary key on our table, and this works fine normally.
The bug is that if the filename contains characters outside of the current ANSI code page, then the select indicates no matches:
SQL: SELECT * FROM "My Designs" WHERE "PATHNAME" = '\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo' [# matches = 0]
However, when the insert is attempted, we get a unique key violation (of course) - since there already is a record with that filename.
Database error: Violation of PRIMARY KEY constraint 'PK__My Desig__1B3D5B4BF643706B'. Cannot insert duplicate key in object 'dbo.My Designs'. The duplicate key value is (\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo).
The statement has been terminated.
I've been over the code with a fine-tooth comb, and I can see nothing wrong. :(
The SQL statement that is being generated produces the correct Unicode output of the filename. Our application is compiled for Unicode. The column is SQL_WVARCHAR in ODBC speak.
I've tried adding AutoTranslate=no to the DSN configuration string, but that appears to have no effect.
I've tried logging the database connection from ODBC control panel. Sadly, that interface produces an ANSI log file - so I cannot verify UNICODE / ANSI issues using that tool.
Questions:
Is there a tool I can use to verify that these statements are being
created / issued correctly by the ODBC driver to the SQL Server
database?
Is there a better way to use ODBC so that the driver doesn't get canoodled by a simple UNICODE string in a SELECT query vs. an INSERT request?
Any other ideas for how to approach this problem (short of replacing our technology)
In the select statement, make sure you enclose the where clause string with a N to tell SQL it's unicode:
..."PATHNAME" = N'\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo'
Also, MFC converts the data to MCBS or UNICODE depending on your configuration. Make sure you use CStringT in recordset.

Informatica Target Table Keyword

How do you use Informatica to load data into a target table whose name is a SQL reserved keyword?
I have a situation where I am trying to use Informatica to populate a table called Union which is failing with the following error:
SQL Server Message: Incorrect syntax near the keywork 'Union'
Database driver error...
Function Name : Execute Multiple
SQL Stmt : INSERT INTO UNION (UnionCode, UnionName, etc )
I have been told that changing the database properties to use quoted identifier would solve this problem; however, I have tried that and it only appears to work for sources, not targets.
And before anyone states the obvious - I cannot change the name of the target table.
Can you please try overriding the table name in session properties as "Union" with the quotes.
Load your data in a table with valid name ,having same structure as union .
And in Post Sql of that target, you can rename the table with whatever name required .
Ex .
Click on the target (XUnion) ,
go to Post Sql and put statement below --
RENAME XUnion to 'UNION' ;
If any table name or column name contains a database reserved word, such as MONTH or YEAR, the session fails with database errors when the Integration Service executes SQL against the database. You can create and maintain a reserved words file, reswords.txt, in the server/bin directory. When the Integration Service initializes a session, it searches for reswords.txt. If the file exists, the Integration Service places quotes around matching reserved words when it executes SQL against the database.
Use the following rules and guidelines when working with reserved words.
The Integration Service searches the reserved words file when it generates SQL to connect to source, target, and lookup databases.
If you override the SQL for a source, target, or lookup, you must enclose any reserved word in quotes.
You may need to enable some databases, such as Microsoft SQL Server and Sybase, to use SQL-92 standards regarding quoted identifiers. Use connection environment SQL to issue the command. For example, use the following command with Microsoft SQL Server:
SET QUOTED_IDENTIFIER ON
Sample reswords.txt File
To use a reserved words file, create a file named reswords.txt and place it in the server/bin directory. Create a section for each database that you need to store reserved words for. Add reserved words used in any table or column name. You do not need to store all reserved words for a database in this file. Database names and reserved words in reswords.txt are not case sensitive.
Following is a sample reswords.txt file:
[Teradata] MONTH DATE INTERVAL [Oracle] OPTION START [DB2] [SQL Server] CURRENT [Informix] [ODBC] MONTH [Sybase]

QSqlQuery using with indexes

I have my own data store mechanism for store data. but I want to implement standards data manipulation and query interface for end users,so I thought QT sql is suitable for my case.
but I still cannot understand how do I involved my indexes for sql query.
let say for example,
I have table with column A(int),B(int),C(int),D(int) and column A is indexed.assume I execute query like select * from Foo where A = 10;
How do I involved my index for search the results?.
You have written your own storage system and want to manipulate it using an SQL like syntax? I don't think Qt SQL is the right tool for that job. It offers connectivity to various SQL servers and is not meant for parsing SQL statements. Qt expects to "pass through" the queries and then somehow parse the result set and transform it into a Qt friendly representation.
So if you only want to have a Qt friendly representation, I wouldn't see a reason to go the indirection with SQL.
But regarding your problem:
In SQL, indexes are usually not stated in the queries, but during the creation of the table schema. But SQL server has a possibility to "hint" indexes, is that what you are looking for?
SELECT column_list FROM table_name WITH (INDEX (index_name) [, ...]);

MySQL C++ Connector: Get the insert_id

I am using mysql connector C++. There is an auto_increament column in my table, I want to get the insert id when I perform an insert action. Does someone know how to get it? Thanks.
My code is something like:
conn->setAutoCommit(0);
pstmt.reset(conn->prepareStatement(insertStr.c_str()));
int updateCount = pstmt->executeUpdate();
conn->commit();
If the API of the library you are using does not provide a method to retrieve the last_insert_id (which seems to be the case for the C++ Connector) you can always do a query
SELECT LAST_INSERT_ID();
which gives you the "value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement." See here for the explanation of MySQL's documentation
UPDATE:
I found this post from a user who is saying the if you do not use auto_increment on your field you can use
SELECT ##identity AS id;