SQL Server datetime culture (localization) headache - sql

SQL Server 2005. Visual Studio 2010. ASP.NET 2.0 Web Application
This is a web application that supports multiple languages, one of them is Korean. I have “langid” in the query string to differentiate different languages, if langid=3 it is Korean.
In my code behind’ C# code, I read a table using this query:
"select * from Reservations where rsv_id = 1234"
There is a column named "rsv_date" in the table which is reservation date, of type datetime. In the db table its value is "11/22/2012 4:14:37 PM". I checked this in SQL server management studio. But when I read it out, I got "2012-11-22 오후 4:14:37"! Where does that Korean “오후” come from??? Is it because of some culture setting anywhere? But I don’t see where, either in my code or in SQL Server. This caused problem for me, because when I modify this record, it will try to write "2012-11-22 오후 4:14:37" to the db, which of course SQL server reports error.
My original code:
Hashtable reservation = new Hashtable();
SqlCommand sqlCommand = null;
SqlDataReader dataReader;
string queryCommand = "select * from Reservations where rsv_id = #RsvID";
sqlCommand = new SqlCommand(queryCommand, getConnection());
sqlCommand.Connection.Open();
sqlCommand.Parameters.AddWithValue("#RsvID", rsvID);
dataReader = sqlCommand.ExecuteReader();
while (dataReader.Read())
{
reservation["rsvID"] = dataReader["rsv_id"];
reservation["rsvCode"] = dataReader["rsv_code"];
reservation["rsvType"] = dataReader["rsv_type"];
reservation["rsvDate"] = dataReader["rsv_date"]; // where does Korean come from?
...
}

It's a common misunderstanding that you can "check" the format of datetime fields in the database.
The format you see on screen will always depend on the client, even if the client is "SQL server management studio".
In the database, the datetime is stored in a binary format that very few need to know.
So, the Korean characters are from the client, in this case your own program.
And Yes, they will depend on some culture setting somewhere.
Your example doesn't show what happens to reservation["rsvDate"] , where is the value displayed with the Korean characters ?
How are you trying to write the value with Korean characters to the database ?
To avoid Korean characters you could use .ToString(CultureInfo.InvariantCulture) where you use the Date value.

Related

Reading SQLite Database with ODBC Provider : Error with fields with float values

Here is the context
I'm building a library in VB.net able to quickly handle SQL Database datas, in windows form based front end. I'm using ADODB Connections and recordsets.
I managed to link front end to Access databases, MS SQL server, MySQL and, recently I'm working on SQLite databases to provide quick and portables SQL providers.
Here is the problem
As I understand it, SQLite stores single/double/float with IEEE-7 standards, and for exemple a stored value of 9.95 will be read as 9,94999980926514.
So when I load the record again, I can edit it (other fields), and update it. but if I try to edit the float value (lets say 9,94999980926514 > 10) then update it, then I've got an error see sample code
Dim LocRs as ADODB.Recordset
LocRs.Open("SELECT ID_Montant,Mont_Value,Mont_Date FROM tMontants",SQLConnection)
LocRs.addNew
LocRs.("ID_Montant").Value =666
LocRs.("Mont_Value").Value =9.95
LocRs.("Mont_Date").Value =Date.Today
LocRs.Update
LocRs.close
'No Problems'
LocRs.open("SELECT ID_Montant,Mont_Value,Mont_Date FROM tMontants WHERE ID_Montant=666",SQLConnection)
LocRs.Mont_Date.Value=Date.Today.AddDays(-2)
Console.WriteLine(LocRs.("Mont_Value").Value) 'Returns 9,94999980926514'
LocRs.Update
LocRs.close
'No Problem again'
LocRs.open("SELECT ID_Montant,Mont_Value,Mont_Date FROM tMontants WHERE ID_Montant=666",SQLConnection)
LocRs.("Mont_Value").Value=10
LocRs.Update
'Error : Row cannot be located for updating. Some values may have been changed since it was last read. Help Code -2147217864'
The error code seems to be of little help.
I'm using
locRs.LockType = LockTypeEnum.adLockOptimistic
locRs.CursorType = CursorTypeEnum.adOpenKeyset
locRs.CursorLocation = CursorLocationEnum.adUseClient
But I tried a lot of combination without success.
As for the provider I'm using Werner ODBC Provider
I Had a similar problem with Date fields.
When editing a field with an incomplete date like 2012-03-01 12:00:00 instead of 2012-03-01 12:00:00.000, But I corrected the problem by formating the date in it's complete form.
Now I'm stuck with this because the SQLite database stores approximates float value whether I rounded it or not before storing it with an update.
I'm guessing it's a provider problem while computing the update because I can do
"UPDATE tMontants SET Mont_Value = 10 WHERE ID_Montant = 666"
Without any problem
But I'd really like to force the recordset to work in order to integrate SQLlite solutions to every software I've deployed so far.
Thanks for your time.

VB.Net Sqlite - Parameterized query not working

I never asked any questions on stackoverflow but it already brought me tons of answers !
But this time, after some extended research, I have to ask it myself.
I'm using VB.Net with Sqlite and my query doesn't return any value when I execute it with parameters. I guess this has something to do with the fact SituationString contains commas but I really can't figure it out.
Here's is my code :
dim ChildCtx as Integer
dim SituationString as String
SituationString="968,970,978,979,980,981,995,1022,1099,1119"
With DataBase
.SQL_CMD.Parameters.Clear()
.SQL_CMD.CommandText = "SELECT SERVCTX_NO FROM SERVCTX WHERE SERVCTX_NO IN (#situationstring) AND MASTER = '1'"
.SQL_CMD.Parameters.Add("#situationstring", SqlDbType.VarChar, 255).Value = SituationString
ChildCtx = .SQL_CMD.ExecuteScalar
.SQL_CMD.Parameters.Clear()
End with
Connection is open and query works out fine if I write the whole query into one string.
Thanks,
You are mixing two techincs: merging constant data into SQL command and using parameters to pass data.
I suppose SituationString is a list of integer you expect for SERVCTX_NO.
So, you must merge it into statement:
.SQL_CMD.CommandText = "SELECT SERVCTX_NO FROM SERVCTX WHERE SERVCTX_NO IN ("+SituationString+") AND MASTER = '1'"
ChildCtx = .SQL_CMD.ExecuteScalar
Using parameters, as you did, SERVCTX_NO would be expected to be a string with 968,970,978,979,980,981,995,1022,1099,1119 exact content!

Error: Column does not exist

I have been able to link PostgreSQL to java. I have been able to display all the records in the table, however I unable to perform delete operation.
Here is my code:
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE MAC = 'kzhdf'";
pst = con.prepareStatement(stm);
pst.executeUpdate();
Please note that MAC is a string field and is written in capital letters. This field does exist in the table.
The error that I am getting:
SEVERE: ERROR: column "mac" does not exist
When it comes to Postgresql and entity names (Tables, Columns, etc.) with UPPER CASE letters, you need to "escape" the word by placing it in "". Please refer to the documentation on this particular subject. So, your example would be written like this:
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = 'kzhdf'";
On a side note, considering you are using prepared statements, you should not be setting the value directly in your SQL statement.
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = ?";
pst = con.prepareStatement(stm);
pst.setString(1, "kzhdf");
pst.executeUpdate();

Oracle database: How to read a BLOB?

I'm working with an Oracle database, and I would like to read the contents of a BLOB. How do I do this?
When I do a simple select statement, it merely returns "(BLOB)" (without the quotes). How do I read the actual contents?
You can dump the value in hex using UTL_RAW.CAST_TO_RAW(UTL_RAW.CAST_TO_VARCHAR2()).
SELECT b FROM foo;
-- (BLOB)
SELECT UTL_RAW.CAST_TO_RAW(UTL_RAW.CAST_TO_VARCHAR2(b))
FROM foo;
-- 1F8B080087CDC1520003F348CDC9C9D75128CF2FCA49D1E30200D7BBCDFC0E000000
This is handy because you this is the same format used for inserting into BLOB columns:
CREATE GLOBAL TEMPORARY TABLE foo (
b BLOB);
INSERT INTO foo VALUES ('1f8b080087cdc1520003f348cdc9c9d75128cf2fca49d1e30200d7bbcdfc0e000000');
DESC foo;
-- Name Null Type
-- ---- ---- ----
-- B BLOB
However, at a certain point (2000 bytes?) the corresponding hex string exceeds Oracle’s maximum string length. If you need to handle that case, you’ll have to combine How do I get textual contents from BLOB in Oracle SQL with the documentation for DMBS_LOB.SUBSTR for a more complicated approach that will allow you to see substrings of the BLOB.
SQL Developer can show the blob as an image (at least it works for jpegs). In the Data view, double click on the BLOB field to get the "pencil" icon. Click on the pencil to get a dialog that will allow you to select a "View As Image" checkbox.
If the content is not too large, you can also use
SELECT CAST ( <blobfield> AS RAW( <maxFieldLength> ) ) FROM <table>;
or
SELECT DUMP ( CAST ( <blobfield> AS RAW( <maxFieldLength> ) ) ) FROM <table>;
This will show you the HEX values.
If you use the Oracle native data provider rather than the Microsoft driver then you can get at all field types
Dim cn As New Oracle.DataAccess.Client.OracleConnection
Dim cm As New Oracle.DataAccess.Client.OracleCommand
Dim dr As Oracle.DataAccess.Client.OracleDataReader
The connection string does not require a Provider value so you would use something like:
"Data Source=myOracle;UserID=Me;Password=secret"
Open the connection:
cn.ConnectionString = "Data Source=myOracle;UserID=Me;Password=secret"
cn.Open()
Attach the command and set the Sql statement
cm.Connection = cn
cm.CommandText = strCommand
Set the Fetch size. I use 4000 because it's as big as a varchar can be
cm.InitialLONGFetchSize = 4000
Start the reader and loop through the records/columns
dr = cm.ExecuteReader
Do while dr.read()
strMyLongString = dr(i)
Loop
You can be more specific with the read, eg dr.GetOracleString(i) dr.GetOracleClob(i) etc. if you first identify the data type in the column. If you're reading a LONG datatype then the simple dr(i) or dr.GetOracleString(i) works fine. The key is to ensure that the InitialLONGFetchSize is big enough for the datatype. Note also that the native driver does not support CommandBehavior.SequentialAccess for the data reader but you don't need it and also, the LONG field does not even have to be the last field in the select statement.
What client do you use? .Net, Java, Ruby, SQLPLUS, SQL DEVELOPER? Where did you write that simple select statement?
And why do you want to read the content of the blob, a blob contains binary data so that data is unreadable. You should use a clob instead of a blob if you want to store text instead of binary content.
I suggest that you download SQL DEVELOPER: http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html . With SQL DEVELOPER you can see the content.
If you're interested to get the plaintext (body part) from a BLOB, you could use the CTX_DOC package.
For example, the CTX_DOC.FILTER procedure can "generate either a plain text or a HTML version of a document". Be aware that CTX_DOC.FILTER requires an index on the BLOB column. If you don't want that, you could use the CTX_DOC.POLICY_FILTER procedure instead, which doesn't require an index.

SQL code import into Access 2007

I basically need to know how to import SQL code into Access. I've tried one way but that requires me to do one table and one value at a time which takes a lot of time.
Can anyone help?
If you are trying to import data, rather than SQL code (see Duffymo's response), there are two ways.
One is to go where the data is and dump a .CSV file and import that, as Duffymo responded.
The other is to create a table link from the Access database to a table in the source database. If the two databases will talk to each other this way, you can use the data in the remote table as if it were in the Access database.
Well, some days ago I needed to shift data from an Access database to SQL (reverse of what you're doing). I found it simpler to write a simple script that would read data from my access database and insert it into SQL.
I don't think doing what you need to do is any different.
I don't know if it will help, but I posting my code (It's a simple C# function). You can just change the connections and it will work. Of course I only had 3 fields so I hard-coded them. You can do the same for your db schema.
protected void btnProcess_Click(object sender, EventArgs e)
{
//Open the connections to the access and SQL databases
string sqlDBCnn = #"Data Source=.\SQLEXPRESS;Integrated Security=True;AttachDBFileName=|DataDirectory|\mydb.mdf;user instance=true";
string accessDBCnn = #"Provider=Microsoft.Jet.OleDB.4.0;Data Source=C:\mydb.mdb";
OleDbConnection cnnAcc = new OleDbConnection(accessDBCnn);
cnnAcc.Open();
SqlConnection cnnSql = new SqlConnection(sqlDBCnn);
cnnSql.Open();
SqlCommand cmSql = new SqlCommand("DELETE tablename", cnnSql);
cmSql.ExecuteNonQuery();
//Retrieve the data from the Access Database
OleDbCommand cmdAcc = new OleDbCommand("SELECT * FROM tablename", cnnAcc);
OleDbDataReader drAcc = cmdAcc.ExecuteReader();
using (drAcc)
{
if (drAcc.HasRows)
{
//Loop through the access database records and add them to the database
while (drAcc.Read())
{
SqlCommand cmdSql = new SqlCommand("INSERT INTO tablename(Category, Head, Val) VALUES(#cat,#head,#val)",cnnSql);
SqlParameter parCat = new SqlParameter("cat",System.Data.SqlDbType.VarChar,150);
SqlParameter parHead = new SqlParameter("head",System.Data.SqlDbType.VarChar,150);
SqlParameter parVal = new SqlParameter("val",System.Data.SqlDbType.VarChar);
parCat.Value = drAcc["Category"].ToString();
parHead.Value = drAcc["Head"].ToString();
parVal.Value = drAcc["Val"].ToString();
cmdSql.Parameters.Add(parCat);
cmdSql.Parameters.Add(parHead);
cmdSql.Parameters.Add(parVal);
cmdSql.ExecuteNonQuery();
}
}
}
lblMsg.Text = "<p /> All Done Kapitone!";
}
SQL code? Or data? "one table and one value" makes me think it's the latter. If so, I'd suggest dumping the data out into a .csv file and importing that into Access tables.
Or maybe using a tool like Microsoft's DTS to map and move the data between sources. That would be the best idea.
I guess you are talking about "importing" both structure and data from SQL to ACCESS. ACCESS does not accept standard TSQL scripts that you could generate directly from your SQL Database. There are some commercial products like EMS that can more or less do the job for you. EMS has a data exporter module that can take your SQL data in different formats, including Access.
Another way would be to open an Access file and write some basic VBA code, taking advantage of the DoCmd.TransferDatabase method, where you can link OR copy tables from other databases into Access.
I forgot if these methods also allow the transfer of a 'clean' database model, including primary keys and relations... You'll have to give it a try.