Changing the NLS_DATE_FORMAT in c# - c#

I am trying to change the NLS_DATE_FORMAT of a query and I am struggling to do so.
I have used two approaches
1st
// Use the command to change the format
OracleCommand cmd = new OracleCommand("ALTER SESSION SET NLS_DATE_FORMAT = \'YYYY-MM-DD\'", conn);
cmd.ExecuteNonQuery();
// Then do another command
OracleCommand mainCommand = new OracleCommand("SELECT * FROM dates_table", conn);
OracleDataReader reader = command.ExecuteReader();
while(reader.Read())
{
// Read Data
}
This option's queries both succeed, yet the date format still contains the time (HH:MM:SS)
2nd
// Put both commands in the same sql statement
string sql = "ALTER SESSION SET NLS_DATE_FORMAT = \'YYYY-MM-DD\';";
sql += "SELECT * FROM dates_table";
OracleCommand command = new OracleCommand(sql, conn);
OracleDataReader reader = command.ExecuteReader();
while(reader.Read())
{
// Read Data
}
This option does not succeed and gives me the error ORA-0091 which seems to be the semicolon in the first statement. I have also tried removing the semicolon, yet it produces a ORA-00922 error.
I am a bit stuck as of now, any help would be greatly appreciated. Thanks in advance!

An oracle DATE is a binary data type and does NOT store a format so when you get the date column in a 3rd-party application (i.e. C#) you will only get the binary data representing years, months, days, hours, minutes and seconds and not any format.
The NLS_DATE_FORMAT session parameter is the internal format Oracle will use in the user's session to implicitly cast dates to (and from) strings.
The SQL/Plus and SQL Developer client applications also use the NLS_DATE_FORMAT session parameter to control how the binary date values are displayed to the user but this formatting is done on the client application (and not by the Oracle database).
If you want to format a DATE data type then do the formatting in C#.
If you really want to format it in the database then use TO_CHAR to convert each date column (without a format) to a formatted string.
SELECT TO_CHAR(date_column, 'YYYY-MM-DD') AS formatted_date_column
FROM dates_table

Related

How to get datetime format of SQL column in C#?

I want to get format of a datetime column to be able to use it in C#. I want to get it and change my variable to this format. I could not find any solution. How to get it? I just want to be able to get the format of existing column and use it as string in C#.
DateTime values in SQL Server are stored as binary values that are not human readable. They are not strings at all.
For C#, you should use the normal .Net primitive DateTime type to talk to the database; NEVER use any string formats; reserve the string for when you output to the user. The ADO.Net library (which also sits underneath other tools like Entity Framework) will efficiently and safely handle transport between your application and SQL Server.
I am building an sql query to search a string value as parameter that comes from frontend.
Great, we can do that. The way we do it to to parse the string to a C# DateTime, and then use the C# DateTime value for the query.
Let me elaborate. I'm worried you're wanting to do something like this:
string SQL = "SELECT * FROM [MyTable] WHERE [DateColumn] >= '" + TextBox1.Text "'";
var cmd = new SqlCommand(SQL, connection);
THAT IS NOT OKAY!
It is NEVER okay to use string concatenation to include user data like that. Instead, you must use parameterized queries. And when you do this, one of the things you can do is provide datetime values.
So instead, the code should look more like this:
string SQL = "SELECT * FROM [MyTable] WHERE [DateColumn] >= #MinDate";
var cmd = new SqlCommand(SQL, connection);
cmd.Parameters.Add("#MinDate", SqlDbType.DateTime).Value = DateTime.Parse(TextBox1.Text);
But even this is still a little rough, because users will do all kinds of things when entering a date into a raw textbox. You'll be much better off if you can also provide a datepicker that ensures you get a clean input from the user.
All that said, the SQL language does have specific formats for Datetime literal values. You can pick any of these formats and the database will handle it correctly:
yyyyMMdd HH:mm:ss[.fff]
yyyy-MM-ddTHH:mm:ss[.fff]
yyyyMMdd
Note the above formats are very specific and must be followed exactly, but if you do any of these can be cleanly converted to SQL Server datetime values. But again: this is not how the values are stored internally, the need for this should be relatively rare, and it's definitely NOT something you would EVER do for user input.

c# ms access date input wrong format

In my program i input a record to MS Access database like this
INSERT INTO Stock VALUES('"+ textCode.Text +"', '#"+ datetimepickerDate.Value +"#', somenumber)
With datetimepicker.Value says 09/06/2022 19:35:14
But for some reason when i open MS Access and checked the record, the date magicaly turns 06/09/2022 19:35:14
I didn't change the datetimepicker's format and it should use system date format, and now i can't select or update the record because of the day and the month switches place.
It works without a problem on my PC, but it wont do with my one specific friend's.
How do i fix this?
Thanks~
Here: '#"+ datetimepickerDate.Value +"#' the following happens:
datetimepickerDate.Value returns a DateTime.
That DateTime is used in string concatenation, which causes an implicit conversion to string, using your system date format (09/06/2022, dd/mm/yyyy).
You add a hash in front and in the back (#09/06/2022#). Now it's a string containing an "MS Access date literal".
The problem is that MS Access date literals are always in the format mm/dd/yyyy. Thus, your day and month value may get "switched", depending on the user's system date format.
Solution: Don't use string concatenation for SQLs, use parameterized SQL instead:
How can I add user-supplied input to an SQL statement?
Example:
var sql = "INSERT INTO Stock VALUES (?, ?, ?)";
using (var cmd = new OleDbCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("", textCode.Text);
cmd.Parameters.AddWithValue("", datetimepickerDate.Value);
cmd.Parameters.AddWithValue("", somenumber);
cmd.ExecuteNonQuery();
}

How to insert ONLY the date (time not included) to ms access database using C#

OleDbCommand command3 = new OleDbCommand();
command3.Connection = connection;
command3.CommandText = "INSERT into AddLoad(ID_Number,Load_Added,Load_Date) values (#ID_Number, #Load_Added,#Load_Date)";
command3.Parameters.AddWithValue("#ID_Number",UserControl_AddLoadConfirmation.INumberValue);
command3.Parameters.AddWithValue("#Load_Added",addbalance);
command3.Parameters.AddWithValue("#Load_Date",DateTime.Now.ToString());
command3.ExecuteNonQuery();
I tried changing the format of my date column (Load_Date) in ms access database to "Short Date" format, when I view all datas to my Datagrid, it still comes with the hour:minute format.
im not sure with the problem maybe it's this code DateTime.Now.ToString()?
If you are going to persist a date or datetime in your database
the type in your database should be datetime (not varchar!)
You should pass DateTime types to your database directly in the command (not a string equivalent)
You should read back a datetime type when querying from the database (not a string equivalent)
So this line
command3.Parameters.AddWithValue("#Load_Date",DateTime.Now.ToString());
Becomes this
command3.Parameters.Add(New OleDbParameter("#Load_Date", OleDbType.Date) { Value = DateTime.Today });
This also ensures that you are passing the correct type to the command so it knows how it is represented in the schema. You really should not call AddWithValue as this does not pass that information in to the command.
Also keep in mind that when working with Ole (ie. access) parameters are positional and not named. That means the order they appear in in the query has to be the same order they appear in within the parameter collection.

execute query in dbf from c#

i am doing a program in C# and i´m trying to execute a query in a DBF files that i think is ok but the value of the HasRows property of the DataReader is false. I think the problem is with the dates. This is my code:
string Con = #"Provider=VFPOLEDB.1;Data Source=\\Server\ges_01";
OleDbConnection ConnectionHandler = new OleDbConnection(Con);
ConnectionHandler.Open();
string SQL = "SELECT codalb FROM BALBARA WHERE FECALB BETWEEN CTOD('2015/12/07') AND CTOD('2015/12/13') AND CODCLI LIKE '%9' ORDER BY CODALB"
OleDbCommand Query = new OleDbCommand(SQL, ConnectionHandler);
OleDbDataReader datareader = Query.ExecuteReader();
while(datareader.Read())
{}
I know the rest is ok because if put string SQL="select codalb from balbara"; Works fine.
Any one can say me what i´m doing wrong
The problem here is that the CTOD() function isn't supported by the OLE DB Provider.
Change your query to use DTOS() which:
Returns a character-string date in a yyyymmdd format from a specified
Date or DateTime expression.
So concluding your query might become to:
string SQL = String.Format(
#"SELECT
codalb
FROM
balbara
WHERE
DTOS(fecalb) BETWEEN '{0}' AND '{1}'
AND codcli LIKE '%9'
ORDER BY
codalb",
dateTimeVariable1.ToString("yyyyMMdd"),
dateTimeVariable2.ToString("yyyyMMdd"));
Note 1: check out the indenting to help you write readable code, also I suggest to write all the column/table names lowercase so you can make an easy difference what is your "data" and what is SQL.
Note 2: you can find offical format string examples about the DateTime type here.
EDIT: As a good advice in comments from #AlanB, you should always strive to use parametrized queries instead of a string to prevent SQL Injection attacks.
A remark about the OLEDB parameters:
The OLE DB .NET Provider does not support named parameters for passing
parameters to an SQL statement or a stored procedure called by an
OleDbCommand when CommandType is set to Text. In this case, the
question mark (?) placeholder must be used.
And about the order of parameters:
Therefore, the order in which OleDbParameter objects are added to the
OleDbParameterCollection must directly correspond to the position of
the question mark placeholder for the parameter in the command text.
So all these informations given your query could look this example:
OleDbCommand Query = new OleDbCommand();
Query.Connection = ConnectionHandler;
Query.CommandText =
#"SELECT
codalb
FROM
balbara
WHERE
DTOS(fecalb) BETWEEN ? AND ?
AND codcli LIKE '%9'
ORDER BY
codalb";
Query.Parameters.Add(dateTimeVariable1.ToString("yyyyMMdd"));
Query.Parameters.Add(dateTimeVariable2.ToString("yyyyMMdd"));
OleDbDataReader datareader = Query.ExecuteReader();

how can it be that this SQL Query work from Oracle SQL Developer but not from code?

i have the following SQL query that works fine (returns multiple rows) when i run it from Oracle's SQL developer tool:
select * from [schema].[table] where resource_unique_name in ('abc123') and (slice_date >= '01-Nov-10') and (slice_date < '01-Dec-10')
but somehow this code below returns 0 records (no errors just, 0 records):
OracleDataReader reader = new OracleDataReader();
const string CONNECTION_STRING = [myConnetionString];
connection.ConnectionString = CONNECTION_STRING;
connection.Open();
OracleCommand command = connection.CreateCommand();
command.CommandText = [same SQL as above];
OracleDataReader reader = command.ExecuteReader();
int rowCount = 0;
while (reader.Read())
{
rowCount++;
}
Console.Write(rowCount);
the connection open's fine because if i hard code a different SQL query i do get results.
is there any reason a query would work fine in SQL query tool but not from my C# code ??
UPDATED NOTE:
in my code, when i remove the:
and (slice_date < '01-Dec-10')
it seems to work fine ( i get data back). Any clue whats wrong with the above criteria ??
I will answer the last part in your update.
'01-Dec-10' is a string. It is not a date. It has nothing to do with dates. Not until it gets converted into a date. There are (to my knowledge) three ways of doing that.
Use TO_DATE()
Specify a date literal as date '2010-12-01', which is always iso date YYYY-MM-DD
Rely on implicit date conversion using the NLS settings (which you are doing)
If your NLS settings is 'DD-MON-RR', the string '01-Dec-10' would get converted into 2010-12-01 (the 1st of december, 2010). If, on the other hand, your settings are 'RR-MON-DD', it would be converted into '2001-12-10' (the 10:th of december, 2001).
I don't know your settings, and since you don't either, you should do the right thing, and that is to always explicitly use TO_DATE() or date literals.
Use ANSI date literals rather than just strings for the date values:
select * from [schema].[table]
where resource_unique_name in ('abc123')
and slice_date >= date '2010-11-01'
and slice_date < date '2010-12-01'

Categories