I have a SQL query that I am passing a C# variable into my Oracle DB.
I am having trouble passing a C# datetime variable, "PROCESS_DATE", into my query in my application. I do not get any records back. If I copy the query into my oracle developer tool, TOAD, it works fine and I get multiple records.
Here is the query I am using in my application:
String SelectAllSQL = "SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = :pPROCESS_DATE";
I also tried converting the datetime variable into a shortDateString() so it matches the database exactly I then used the TO_DATE function, which I have to use if I query dates directly in TOAD, without any luck. The shortDateString() changes my date into: 1/16/2016, which is what I need, but the OracleDataReader does not like it. Here it the query with the TO_DATE function:
String SelectAllSQL = "SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = TO_DATE(:pPROCESS_DATE, 'MM-DD-YYYY'";
:pROCESS_DATE is a datetime variable that is passed in.
There must be a breakdown between C# and Oracle in relation to handling a datetime variable. I am using Oracle DataReader to handle the processing of the query.
OracleDataReader dataReader = mDataAccess.SelectSqlRows ( oracleConnection, oracleCommand, sqlCommand, parameters );
while ( dataReader.Read ( ) )
{
groupEntityFacilityRptList.Add ( ReadRecord ( dataReader ) );
}
If I use the TO_DATE function, the application will not step into the while loop. If I use the original query, it does but returns no data.
The datetime variable PROCESSDATE looks like this:
1/16/2016 12:00:00 AM
I notice it has a timestamp on it, so I'm not sure if that is the problem or not.
The data in Oracle is like this:
1/16/2016
Unless I've totally misunderstood your issue, I think you might be making this harder than it needs to be. ODP.net handles all of that dirty work for you. If PROCESS_DATE is an actual DATE datatype in Oracle, then you just need to pass an actual C# DateTime variable to it and let ODP.net do the heavy lifting. There is no need to do conversion of any type, provided you are passing an actual date:
DateTime testDate = new DateTime(2015, 7, 16);
OracleCommand cmd = new OracleCommand(
"SELECT * FROM REALMS_AUDIT.R2_GROUP_QUERY_RPT WHERE PROCESS_DATE = :pPROCESS_DATE",
conn);
cmd.Parameters.Add(new OracleParameter("pPROCESS_DATE", OracleDbType.Date));
cmd.Parameters[0].Value = testDate;
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
object o = reader.IsDBNull(0) ? null : reader.GetValue(0);
}
reader.Close();
If your data in C# is not a date, I'd recommend making it one before even trying:
DateTime testDate;
if (DateTime.TryParse(testDateString, out testDate))
{
// run your query
}
As per my comment, please try below and see this resolves.
TRUNC(TO_DATE(:pPROCESS_DATE,'MM-DD-YYYY HH:MI:SS AM')) if pROCESS_DATE format is 1/16/2016 12:00:00 AM.
TRUNC(TO_DATE(:pPROCESS_DATE,'DD-MM-YYYY HH:MI:SS AM')) if pROCESS_DATE format is 16/1/2016 12:00:00 AM.
First, I learned that my code will not go into the code below unless I actually have records returned to me.
OracleDataReader dataReader = mDataAccess.SelectSqlRows ( oracleConnection, oracleCommand, sqlCommand, parameters );
while ( dataReader.Read ( ) )
{
groupEntityFacilityRptList.Add ( ReadRecord ( dataReader ) );
}
Second, to get ProcessDate to work, I needed to take the string that was coming from my View, convert it to a datetime, and then I formatted it back as a string. It may not be best practices but it worked.
public JsonResult GetGroupReportData ( String reportDate )
{
DateTime processDate = DateTime.Parse ( reportDate );
var monthlyReport = SelectAllGroupRprt (processDate.ToString("MM/dd/yyyy");
return new JsonResult ( )
{
Data = monthly,
MaxJsonLength = Int32.MaxValue
};
}
Related
In my app, I am trying to grab a date from the database and compare it against local time. Right now I am getting an error when I am converting to date incorrectly.
I have tried:
Convert.ToDateTime()
DateTime.ParseExact()
My code:
string time = "Select top(1) DATE from SERVICE order by DATE desc";
SqlCommand command = new SqlCommand(time, connection);
connection.Open();
using (SqlDataReader timereader = timecommand.ExecuteReader())
{
while (timereader.Read())
{
if (DateTime.ParseExact(time, "yyyy-MM-dd HH:mm:ss", null).AddMinutes(10) > currenttime)
{
// code
}
}
connection.Close();
}
I am hoping when I retrieve this value from the database, I can convert it into a proper datetime value and compare against local time and run other code after that.
At the moment I am just getting this error:
The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.
I'm probably just dumb and missing something obvious..
Your query selects a single value. Use ExecuteScalar and cast it to a DateTime (it's already a DateTime, but boxed inside an object):
string time = "Select top(1) DATE from SERVICE order by DATE desc";
SqlCommand command = new SqlCommand(time, connection);
connection.Open();
DateTime d = (DateTime)command.ExecuteScalar();
connection.Close();
After you do this, and before you embark on some long mission of this protracted way of getting data out of a database, converting it to objects for use in your app etc, take a look at least at an ORM called Dapper, if not Entity Framework. Dapper's basically what you're doing now, but it auto converts your queries to objects and back and saves a lot of tedious code. With Dapper it'd look more like:
using (var connection = new SqlConnection("connstr"))
{
var d = connection.QuerySingle<DateTime>("SELECT TOP 1 Date FROM ...");
}
Yes, it's not much of a saving over what you have now, right? But what if you have a list of Order that themselves have 20 properties:
using (var connection = new SqlConnection("connstr"))
{
var orders = connection.Query<Order>("SELECT * FROM order WHERE customerID = #custid", new {custid = 123}).ToList();
}
Orders is now a list of Order objects for customer 123, parameterized, injection safe, quick and a one liner to read and populate your orders; doing that in a datareader is going to take at least 25 lines of boring code
http://dapper-tutorial.net and spend 2 minutes reading; I'll lay bets you'll be glad you did
Just try to read the value as a proper, native DateTime type like this (assuming that the DATE column in SQL Server is in fact a DATETIME or similar datatype - not a string - hopefully!):
using (SqlDataReader timereader = timecommand.ExecuteReader())
{
while (timereader.Read())
{
// just read the DateTime value as such
DateTime dt = timereader.GetDateTime(0);
// then do whatever you need to do with this DateTime value .....
}
connection.Close();
}
I m using user define table parameter for bulk insert, i create the user define table and column name is ModifiedDate in datatype for datetime
when i pass the value into sql it will insert fine but it missed milliseconds value then how can i install this
My user define table
CREATE TYPE [dbo].[Test] AS TABLE(
[ModifiedDate] [datetime] NOT NULL,
)
My Sp
ALTER PROCEDURE [dbo].[CP_UpdateData]
-- Add the parameters for the stored procedure here
#Test Test Readonly,
INSERT into Test(ModifiedDate)
Values(ModifiedDate);
but here my datetime value is missing millisecond, could you please help any suggestion for resolve this issues
in by c# code
using (var cmd = new SqlCommand())
{
cmd.CommandText = "CP_UpdateData";
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("Test", SqlDbType.Structured).Value = ConvertToDataTable(list);
con.Open();
var dataReader = await cmd.ExecuteReaderAsync();
}
public DataTable ConvertToDataTableCampaingList(List<Test> list)
{
var dataTable = new DataTable();
if (list != null && list.Count > 0)
{
dataTable.Columns.Add("ModifiedDate", Type.GetType("System.DateTime"));
foreach (var data in list)
{
var dataRow = dataTable.NewRow();
dataRow["ModifiedDate"] = data.ModifiedDate;
dataTable.Rows.Add(dataRow);
}
}
return dataTable;
}
The answer being in the CHAT ROOM discussion, I will post it here:
The problem is implicit conversions and how each compiler treats the data. DATETIME by default has no defined FORMAT, so SQL implicitly converts the data.
So the issue is when your storing it into the table as the Default
formatting is the problem CREATE TABLE #Example2 (TIMES DATETIME NOT
NULL) INSERT INTO #Example2 (TIMES) VALUES (CONVERT(DATETIME,
GETDATE(), 9)) , (CAST(GETDATE() AS VARCHAR(20) ) ) Notice how the
default in a simple string actually drops milliseconds since its
format is wrong
Notice the solution was explicitly defining the format:
Manikandan wrote:
When i convert the var date =
(DateTime.Parse(datetime.ToString("yyyy-MM-dd HH:mm:ss.fff"))); it
return correct milliseconds
Converting the DATETIME to string makes it portable and in a data type that will not TRUNCATE the data. However, use a proper CONVERT(data type, expression, style) if you ensure accuracy.
Manikandan wrote:
DECLARE #TEMP_Result TABLE
(
ModifiedDate DATETIME
)
DECLARE #TEMp TABLE
(
ModifiedDate varchar(50)
)
declare #timestring varchar(50)
set #timestring = '2016-06-28 12:53:20.850'
Insert into #TEMp(ModifiedDate)
values(#timestring)
Insert into #TEMP_Result(ModifiedDate)
select Convert(datetime, ModifiedDate) from #TEMp
select * from #TEMP_Result
MORAL: BEWARE OF IMPLICIT CONVERSIONS
Implicit conversion are guesses and determined by the compiler. They are not dependable as this case shows.
CAST is not an explicit conversion, and may return the wrong format. Use CONVERT in SQL to avoid implicit conversions.
Storing DATETIME in a string makes it portable, avoids TRUNCATION of data, and is easily converted to the correct format in SQL.
I want to add lotno,date,catid,rcno from a table lot and local c# variables buyid,prc,datetime, all to the table soldlot. How do I do this? Im using MySql.
string datetime = DateTime.Today.ToString("yyyy-MM-dd");
String q6 = "insert into soldlot (lotNo,date,categoryId,receiptNo) (select #lotno,date,#catid,#rcno from lot)";
MySqlCommand c6 = new MySqlCommand(q6, cn);
c6.Parameters.Add("#lotno",lotno);
c6.Parameters.Add("#catid",catid);
c6.Parameters.Add("#buyerId", buyid);
c6.Parameters.Add("#rcno", rcno);
c6.Parameters.Add("#soldPrice", prc);
c6.Parameters.Add("#soldDate", datetime);
c6.ExecuteNonQuery();
When you say;
select #lotno,date,#catid,#rcno from lot
You try to parameterize your column names, not your values.
You need to use them like;
select lotno, date, catid, rcno from lot
where lotno = #lotno and date = #date and catid = #catid and rcno = #rcno
Read 13.2.5 INSERT Syntax
And looks like you don't need #buyerId, #soldPrice and #soldDate because you didn't even define them in your command.
If you wanna save your DateTime values, don't store in any character typed column. Use datetime or relevant type and pass your DateTime values directly to your parameterized queries.
Also use using statement to dispose your database connections and objects as well.
string sqlUserName3 = "SELECT out_date FROM status where s_id='" + TextBox2.Text + "'";
SqlCommand sqlcmd3 = new SqlCommand(sqlUserName3, sqlcon);
sqlUserName4 = "SELECT in_date FROM status where s_id='"+TextBox2.Text+"'";
SqlCommand sqlcmd4 = new SqlCommand(sqlUserName4, sqlcon);
string q3 = sqlcmd3.ExecuteNonQuery().ToString();
string q4 = sqlcmd4.ExecuteNonQuery().ToString();
DateTime dt1 = DateTime.Parse(q3);
DateTime dt2 = DateTime.Parse(q4);
TimeSpan result = dt1.Subtract(dt2);
string result1 = result.ToString();
TextBox8.Text = result1;
//Response.Redirect("login.aspx");
sqlcon.Close();
There are many things wrong with your code at the moment:
You shouldn't use string concatenation to build your query. Use parameterized SQL instead. This will avoid SQL injection attacks and conversion issues
You're using ExecuteNonQuery when you're trying to execute... a query.
You're converting the results into a string which is a bad idea even if it did return a date... instead, get the results in a form you can fetch as just a DateTime. Avoid string conversions wherever you can.
So you should:
Use parameters instead of dynamic SQL
Use ExecuteReader and get the first result from each reader
Use the GetDateTime method to get the DateTime from the results.
I would personally use the subtraction operator afterwards, too:
TimeSpan difference = end - start;
... but that's just a matter of preference, and not an actual mistake in your current code.
Your mistake is here:
string q3 = sqlcmd3.ExecuteNonQuery().ToString();
string q4 = sqlcmd4.ExecuteNonQuery().ToString();
DateTime dt1 = DateTime.Parse(q3);
DateTime dt2 = DateTime.Parse(q4);
ExecuteNonQuery does not return a date in a string representation. It returns the number of records affected by the query; hence, when you run DateTime.Parse(number) you get an error.
None of your queries are returning a date so it's unclear how you expect to get a date back from calling the SQL you have in your question...
Update
Do not use string concatenation to build your SQL Statements. You can use parameters to avoid exposing yourself to SQL Injection attacks. One example would be:
string sqlUserName3 = "SELECT out_date FROM status where s_id=#id";
SqlCommand sqlcmd3 = new SqlCommand(sqlUserName3, sqlcon);
sqlcmd3.Parameters.AddWithValue("#id",TextBox2.Text );
You use SqlCommand.ExecuteNonQuery() but you need SqlCommand.ExecuteScalar(). The first function returns nothing, it's supposed to be used for queries like insert or update. The second returns value of first cell of first row of query output.
You should use execute scalar or pass some out parameter to get value. This should get you some value in q3 and q4.
Now to avoid erros you should also use DateTime.ParseExact instead of simple Parse.
DateTime dt1 = DateTime.ParseExact(q3,"dd/mm/yyyy HH:mm",CultureInfo.InvariantCulture);
DateTime dt2 = DateTime.ParseExact(q4,"dd/mm/yyyy HH:mm",CultureInfo.InvariantCulture);
Trying to set a datetime field in a SQL table to NULL if the textbox is empty, I can't seem to get this to work.
string EndDate = "";
if (String.IsNullOrEmpty(EndDateTxtBox.Text.Trim()))
{
EndDate = null;
}
else
{
EndDate = EndDateTxtBox.Text;
}
var sql = String.Format(#"UPDATE Test SET StartDate='{0}',
EndDate='{1}' WHERE ID = '{2}'",
StartDateTxtBox.Text, EndDate, id);
When I do this and put in a break point I get this for "var sql':
"UPDATE Test SET StartDate='5/23/2013', EndDate=" WHERE ID = '19'"
I tried removing the ' from the sql string but that didn't work either. Any suggestions?
Edit: I understand the importance of preventing against SQL injection but this a page on my internal web server for my use only and not projected to the public. It's to help me keep track of personal things.
Parameterize.
First, you should move the UI code away from the database code, so that by the time it gets anywhere near the DB we have correctly typed data. For example:
void UpdateDates(int id, DateTime startDate, DateTime? endDate) {...}
and put whatever Parse etc code you want at the caller - not near the db. Now we need to implement that:
void UpdateDates(int id, DateTime startDate, DateTime? endDate) {
//... where-ever cmd comes from, etc
cmd.CommandText =
"update Test set StartDate=#start, EndDate=#end where ID = #id";
cmd.Parameters.AddWithValue("id", id);
cmd.Parameters.AddWithValue("start", startDate);
cmd.Parameters.AddWithValue("end", (object)endDate ?? DBNull.Value);
cmd.ExecuteNonQuery();
// ... cleanup etc
}
Or with a tool like "dapper":
void UpdateDates(int id, DateTime startDate, EndDate? endDate) {
//... where-ever connection comes from, etc
connection.Execute(
"update Test set StartDate=#start, EndDate=#end where ID = #id",
new { id, start = startDate, end = endDate}); // painfully easy
// ... cleanup etc
}
It sounds like the problem is the single quotes. If it is NULL then you shouldn't have them.
Also, you probably want to be using a parameterized query (for safety reasons and pass in the values). In that case the quotes shouldn't be necessary either.
Notwithstanding the issues in your code that are not regarded as SQL best practices within C# code, you have several issues:
You're setting EndDate to a C# null. That is not the same as an SQL NULL, which is denoted as DBNull.Value
You have no regard for the fact that NULL doesn't need quotes in SQL, so your SQL would need to be different anyway in order to work even if you fix #1.
I suggest to write a Stored Procedure; if the end date textbox is null, just don't pass that parameter, and make it have a default value of NULL in the stored proc.
Create Procedure usp_TestDateRange_Update
( #ID int -- or whatever type your ID is
#StartDate DateTime,
#EndDate DateTime = NULL)
As
Update Test
Set StartDate = #StartDate,
EndDate = #EndDate
Where ID = #ID
Something like that. Now what you need to do is make your C# code call the stored procedure and add the parameters to the call from your textboxes.
I think the error is in the string.format line. you cannot include a line break in the string portion. Try one of the following.
var sql = String.Format(
#"UPDATE Test SET StartDate='{0}', EndDate='{1}' WHERE ID = '{2}'",
StartDateTxtBox.Text, EndDate, id);
or,
var sql = String.Format(#"UPDATE Test SET StartDate='{0}', " +
"EndDate='{1}' WHERE ID = '{2}'",
StartDateTxtBox.Text, EndDate, id);
but, as other answers here mention, you should learn about SQL injection and consider another approach.
You can try this way:
string sql = String.Format(#"UPDATE Test SET StartDate={0},
EndDate={1} WHERE ID = {2}",
(StartDateTxtBox.Text.Trim().Equals(string.Empty) ? StartDateTxtBox.Text:"NULL"), EndDate, id);