How do you properly update a mysql field with NULL? - mysql

How does one properly update a mysql field with a NULL value when using a variable in the sql query?
I have a variable called $timestamp. When it's set to date( Y-m-d h:i:s ) I have to wrap it in quotes because I'm passing a string in my mysql query. When $timestamp is set to NULL, the database query contains '' as the value for $timestamp and the field updates to 0000-00-00 00:00:00. It's important to keep this field as NULL to show that the process has never been run before.
I don't want to use now() because then my sql statement is not in sync with my class variable $timestamp.
I don't want to set $timestamp to 'NULL' because then that variable is not accurate. It's no longer NULL, it's set to a string that contains the word NULL.
What am I missing here?

The correct SQL syntax to set a column to NULL is:
UPDATE Table SET Column = NULL WHERE . . .
(note the lack of quotes around the literal NULL).
Are you performing this UPDATE using SQL or using some kind of framework? If a framework, it should recognize NULL values and pass them to the database correctly for you.

After a lot of research, I've found that this is a well known problem with no good solution if you are writing your sql queries outright.
The correct solution is to use a database abstraction layer like PDO ( for PHP ), or Active Record ( used in frameworks like Codeignitor and Ruby on Rails ).

Related

In MySQL, can I get the column type and and check column values in a single SELECT statement?

I'll start this off by saying I know that there are more practical ways to solve this. It's more of an intellectual curiosity than anything else.
I've inherited a MySQL database where some columns are stored as varchar(5) but actually contain the literals "True" or "False". Changing the structure of the data is not an option right now due to other issues. I'm mapping the columns to an ORM (SQLAlchemy), and I want the column to be mapped to a Boolean data type in the supporting codebase using a type adapter. (I've written this adapter already; it's not the problem.)
To help make the mapping process faster, I'm writing a small query to look at the INFORMATION_SCHEMA table and build a line of Python code defining the column using the ORM's syntax. I cannot assume that the data type varchar(5) is a Boolean column - I need to inspect the contents of that column to see if there are values contained in it besides True and False.
Can I write a query that will both get the column type from INFORMATION_SCHEMA and check the actual values stored in that column?
Here is the query I have so far:
SELECT CONCAT(
"Column(""",
col.column_name,
""", ",
(CASE
WHEN col.DATA_TYPE = "int" THEN "Integer"
-- Code in question
WHEN
col.DATA_TYPE = "varchar"
AND col.CHARACTER_MAXIMUM_LENGTH = 5
AND NOT EXISTS(
-- Doesn't seem to work
SELECT DISTINCT col.COLUMN_NAME
FROM col.TABLE_NAME
WHERE col.COLUMN_NAME NOT IN ("True", "False")
)
THEN "BoolStoredAsVarchar"
WHEN col.DATA_TYPE = "varchar" THEN CONCAT("String(", col.CHARACTER_MAXIMUM_LENGTH, ")")
-- Default if it's not a recognized column type
ELSE col.DATA_TYPE
END),
"),"
) AS alchemy
FROM information_schema.columns AS col
WHERE
col.TABLE_SCHEMA = "my_schema"
AND col.TABLE_NAME = "my_table"
ORDER BY col.ORDINAL_POSITION;
Running this code gives me a permissions error: Error Code: 1142. SELECT command denied to user 'user'#'host' for table 'table_name'. Presumably it's trying to use col.TABLE_NAME as a literal instead of interpreting it.
I've also tried creating a simple stored procedure and making table_name into a variable. However, replacing the FROM clause inside the EXISTS with a variable name gives me a syntax error instead.
Again, it's easy enough to run the query myself to see what's in that column. I'd just like to know if this is possible, and if so, how to do it.
You can't do what you're trying to do in a single query.
The reason is that table names (or any other identifier) must be fixed in the query at the time it is parsed, which is before it has read any values from tables. Thus you can't read the name of a table as a string from information_schema and also read from the table with that name in the same query.
You must read the table name from information_schema and then use that result to format a second query.
This isn't a problem specific to MySQL. It's true of any SQL implementation.

Google Apps Script - MySQL data import using JDCB does not work with Date 0000-00-00 [duplicate]

I have a database table containing dates
(`date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00').
I'm using MySQL. From the program sometimes data is passed without the date to the database. So, the date value is auto assigned to 0000-00-00 00:00:00
when the table data is called with the date column it gives error
...'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp.......
I tried to pass null value to the date when inserting data, but it gets assign to the current time.
Is there any way I can get the ResultSet without changing the table structure?
You can use this JDBC URL directly in your data source configuration:
jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull
Whether or not the "date" '0000-00-00" is a valid "date" is irrelevant to the question.
"Just change the database" is seldom a viable solution.
Facts:
MySQL allows a date with the value of zeros.
This "feature" enjoys widespread use with other languages.
So, if I "just change the database", thousands of lines of PHP code will break.
Java programmers need to accept the MySQL zero-date and they need to put a zero date back into the database, when other languages rely on this "feature".
A programmer connecting to MySQL needs to handle null and 0000-00-00 as well as valid dates. Changing 0000-00-00 to null is not a viable option, because then you can no longer determine if the date was expected to be 0000-00-00 for writing back to the database.
For 0000-00-00, I suggest checking the date value as a string, then changing it to ("y",1), or ("yyyy-MM-dd",0001-01-01), or into any invalid MySQL date (less than year 1000, iirc). MySQL has another "feature": low dates are automatically converted to 0000-00-00.
I realize my suggestion is a kludge. But so is MySQL's date handling.
And two kludges don't make it right. The fact of the matter is, many programmers will have to handle MySQL zero-dates forever.
Append the following statement to the JDBC-mysql protocol:
?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
for example:
jdbc:mysql://localhost/infra?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
Instead of using fake dates like 0000-00-00 00:00:00 or 0001-01-01 00:00:00 (the latter should be accepted as it is a valid date), change your database schema, to allow NULL values.
ALTER TABLE table_name MODIFY COLUMN date TIMESTAMP NULL
As an exteme turnaround, when you cannot do an alter to your date column or to update the values, or while these modifications take place, you can do a select using a case/when.
SELECT CASE ModificationDate WHEN '0000-00-00 00:00:00' THEN '1970-01-01 01:00:00' ELSE ModificationDate END AS ModificationDate FROM Project WHERE projectId=1;
you can try like This
ArrayList<String> dtlst = new ArrayList<String>();
String qry1 = "select dt_tracker from gs";
Statement prepst = conn.createStatement();
ResultSet rst = prepst.executeQuery(qry1);
while(rst.next())
{
String dt = "";
try
{
dt = rst.getDate("dt_tracker")+" "+rst.getTime("dt_tracker");
}
catch(Exception e)
{
dt = "0000-00-00 00:00:00";
}
dtlst.add(dt);
}
I wrestled with this problem and implemented the URL concatenation solution contributed by #Kushan in the accepted answer above. It worked in my local MySql instance. But when I deployed my Play/Scala app to Heroku it no longer would work. Heroku also concatenates several args to the DB URL that they provide users, and this solution, because of Heroku's use concatenation of "?" before their own set of args, will not work. However I found a different solution which seems to work equally well.
SET sql_mode = 'NO_ZERO_DATE';
I put this in my table descriptions and it solved the problem of
'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
There was no year 0000 and there is no month 00 or day 00. I suggest you try
0001-01-01 00:00:00
While a year 0 has been defined in some standards, it is more likely to be confusing than useful IMHO.
just cast the field as char
Eg: cast(updatedate) as char as updatedate
I know this is going to be a late answer, however here is the most correct answer.
In MySQL database, change your timestamp default value into CURRENT_TIMESTAMP. If you have old records with the fake value, you will have to manually fix them.
You can remove the "not null" property from your column in mysql table if not necessary. when you remove "not null" property no need for "0000-00-00 00:00:00" conversion and problem is gone.
At least worked for me.
I believe this is help full for who are getting this below Exception on to pumping data through logstash
Error: logstash.inputs.jdbc - Exception when executing JDBC query {:exception=>#}
Answer:jdbc:mysql://localhost:3306/database_name?zeroDateTimeBehavior=convertToNull"
or if you are working with mysql

Select NULL as column using JOOQ

I'm trying to select NULL as a column in my query using JOOQ, so basically something like this:
SELECT name, NULL as 'someColumn' FROM someTable;
I need to do this, because the result needs to include someColumn (as part of a data standard), but we do not have this information in our database. This works fine in plain SQL, but I'm struggling to reproduce this using JOOQ.
Does anyone know how to do this in a query of this form?
context.select(
SOMETABLE.NAME,
... // Other columns here
DSL.NULL.as("someColumn") // <-- This doesn't exist
)
You can use an inline value
DSL.inline(null)
Depending on your database dialect or query usage, you may need to add a data type to that value, e.g.
DSL.inline(null, SQLDataType.VARCHAR)

Could this simple T-SQL update fail when running on multiple processors?

Assuming that all values of MBR_DTH_DT evaluate to a Date data type other than the value '00000000', could the following UPDATE SQL fail when running on multiple processors if the CAST were performed before the filter by racing threads?
UPDATE a
SET a.[MBR_DTH_DT] = cast(a.[MBR_DTH_DT] as date)
FROM [IPDP_MEMBER_DEMOGRAPHIC_DECBR] a
WHERE a.[MBR_DTH_DT] <> '00000000'
I am trying to find the source of the following error
Error: 2014-01-30 04:42:47.67
Code: 0xC002F210
Source: Execute csp_load_ipdp_member_demographic Execute SQL Task
Description: Executing the query "exec dbo.csp_load_ipdp_member_demographic" failed with the following error: "Conversion failed when converting date and/or time from character string.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
End Error
It could be another UPDATE or INSERT query, but the otehrs in question appear to have data that is proeprly typed from what I see,, so I am left onbly with the above.
No, it simply sounds like you have bad data in the MBR_DTH_DT column, which is VARCHAR but should be a date (once you clean out the bad data).
You can identify those rows using:
SELECT MBR_DTH_DT
FROM dbo.IPDP_MEMBER_DEMOGRAPHIC_DECBR
WHERE ISDATE(MBR_DTH_DT) = 0;
Now, you may only get rows that happen to match the where clause you're using to filter (e.g. MBR_DTH_DT = '00000000').
This has nothing to do with multiple processors, race conditions, etc. It's just that SQL Server can try to perform the cast before it applies the filter.
Randy suggests adding an additional clause, but this is not enough, because the CAST can still happen before any/all filters. You usually work around this by something like this (though it makes absolutely no sense in your case, when everything is the same column):
UPDATE dbo.IPDP_MEMBER_DEMOGRAPHIC_DECBR
SET MBR_DTH_DT = CASE
WHEN ISDATE(MBR_DTH_DT) = 1 THEN CAST(MBR_DTH_DT AS DATE)
ELSE MBR_DTH_DT END
WHERE MBR_DTH_DT <> '00000000';
(I'm not sure why in the question you're using UPDATE alias FROM table AS alias syntax; with a single-table update, this only serves to make the syntax more convoluted.)
However, in this case, this does you absolutely no good; since the target column is a string, you're just trying to convert a string to a date and back to a string again.
The real solution: stop using strings to store dates, and stop using token strings like '00000000' to denote that a date isn't available. Either use a dimension table for your dates or just live with NULL already.
Not likely. Even with multiple processors, there is no guarantee the query will processed in parallel.
Why not try something like this, assuming you're using SQL Server 2012. Even if you're not, you could write a UDF to validate a date like this.
UPDATE a
SET a.[MBR_DTH_DT] = cast(a.[MBR_DTH_DT] as date)
FROM [IPDP_MEMBER_DEMOGRAPHIC_DECBR] a
WHERE a.[MBR_DTH_DT] <> '00000000' And IsDate(MBR_DTH_DT) = 1
Most likely you have bad data are are not aware of it.
Whoops, just checked. IsDate has been available since SQL 2005. So try using it.

Simple query condition in sql

I have a Query - - < This Is a valid Query >
'SELECT *
FROM MyTable
WHERE city= ?
ORDER BY name ' [Keyname]
I am using this queried condition :: i am passing the Keyname as params from client to this sql query
This works & i get the required result BUT
If i pass nothing say null comes from client as param value for Keyname......... this query fails
how can i make the better query ... so that even if null comes ....
ORDER BY condition is satisfied
Or
R there other solution i need to look for
If so ... what is it ?
Hope i am clear
[EDIT]
CASE1:: for the url
http://54.218.73.244:7005/DescriptionSortedSearchRating/?Key=Pune
my told query satisfies::
But
http://54.218.73.244:7005/DescriptionSortedSearchRating/?Key=
my query fails, my sql query is expecting a Key for http://54.218.73.244:7005/DescriptionSortedSearchRating/ ..... if i pass nothing my query dosent get me a result..
.
what i am trying to see is even if i get nothing as key ORDER BY condition must be met ...
IF I PASS A KEY VALUE
IF I DONT PASS A KEY VALUE
You can clearly see i am not able to fetch results from database (Empty JSON)
This question doesn't have anything to do with MySQL. This is 100% your high level language. The null value the [Keyname] has is a null value in the language you're using to create the string that will be the final query.
The simplest solution will be not to assign null to your [Keyname] variable but rather an empty string.
You may use this:
ORDER BY name CASE WHEN Keyname IS NULL THEN '' ELSE CONCAT(',', Keyname) END
I am not sure whether the syntax is fine or not. But what I expect here to append empty string when Keyname is null and to append the Keyname with a comma (,). Please try it.
Other option is using function ISNULL
ISNULL(Keyname, '');