I have a text column in one of my MS Access tables that is empty be default when a new record is inserted. The problem I have is that I can't seem to check whether this field is empty with EITHER equals Null or equals "" . For example, neither of these "reads" the field as being empty:
If [Field] = "" Or [Field] = Null Then
I've always used Access 2007 to develop this database, and I recently opened it with Access 2003, which is when I think this problem started. Could that be the cause? If so, would simply opening and saving it again with Access 2007 solve it?
When you compare against null, you need to use the IsNull function. With traditional ANSI SQL logic, Null <> Null, so you need a special function to test for null.
If [Field] = "" Or IsNull([Field])
First off, I would suggest that you do one of two things:
set your fields to disallow zero-length strings. That way you'd have to test only Is Null.
if you feel you must allow storage of ZLS, then set the default value to a ZLS. It's still possible for the field to end up Null, though, so this may or may not be helpful.
I don't see storage of ZLS's as having any utility whatsoever. It's almost always a shortcut to accomodate data being appended from sources that return ZLS's instead of Nulls for empty fields.
You should also read up on Nulls. Allen Browne has a number of pages that explain it all quite well:
Nulls: Do I need them?
Common Errors with Null
Aspects of working with Nulls in VBA code:
Nothing? Empty? Missing? Null?
The articles are Access-oriented, but could be valuable to those using any database, particularly relative novices because of the conversational style of the writing.
You should try:
If Nz([Field], "") = "" Then
Because:
If [Field] = ""
in:
If [Field] = "" Or IsNull([Field])
Would still throw a Null Error!
Related
When trying the following command below, my database still shows null values. Could anyone please assist?
Update AmazingAmazonians.Product set URL= "http://www.google.com" where URL='';
There's a world of difference between an empty string and actual NULL values. You may need:
WHERE URL IS NULL
Remember, NULL is not comparable with = or !=, you need to use the IS or IS NOT operators.
I have a column in my MySQL database which is of type TINYINT(1). I need to store actual integers in this column. The problem is, because of the column type, Rails 4.1 assumes this column contains only boolean values, so it typecasts all values besides 0 or 1 to be 0 when it writes to the database.
I don't want to simply disable boolean emulation since we have a number of columns in our database where we use TINYINT(1) to actually represent a boolean value. And I am currently not able to change the column types in MySQL.
How can I force Rails 4.1 to bypass the typecasting step and write directly to the database instead?
(This excerpt from the Rails 4.1 source may be of some use: https://github.com/rails/rails/blob/4-1-stable/activerecord/lib/active_record/attribute_methods/write.rb)
Could you use raw SQL to do the insert?
Something like:
sql = "INSERT INTO my_table (smallnumber) VALUES (100)"
ActiveRecord::Base.connection.execute(sql)
I don't know if it works but you can try to overwrite the setter using the method :raw_write_attribute or :write_attribute. The :raw_write_attribute and :write_attribute methods disable/enable the type casting before writing.
Let's say the attribute/column is called :the_boolean_column_who_wanted_to_be_an_integer, you can probably do something like:
def the_boolean_column_who_wanted_to_be_an_integer=(value)
raw_write_attribute(:the_boolean_column_who_wanted_to_be_an_integer, value) # or write_attribute(...
end
Does it work?
Maybe you should overwrite the setter completely, using rails 4.1 source code:
def the_field=(value)
attr_name = 'the_field'
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
#attributes_cache.delete(attr_name)
column = column_for_attribute(attr_name)
# If we're dealing with a binary column, write the data to the cache
# so we don't attempt to typecast multiple times.
if column && column.binary?
#attributes_cache[attr_name] = value
end
if column || #attributes.has_key?(attr_name)
#attributes[attr_name] = value
else
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
end
end
Note that #attributes[attr_name] = send(type_cast_method, column, value) has been changed to #attributes[attr_name] = value . You can probably simplify it for your use case. Also note that I haven't tried this, and even if it works, you should be careful whenever you want to upgrade rails.
Plan A: Change to SMALLINT (2 bytes) as a compromise.
Plan B: See if TINYINT(3) will fool Rails into not thinking it is Boolean.
Plan C: See if TINYINT UNSIGNED will fool Rails into not thinking it is Boolean. (This assumes your number are non-negative: 0..255.)
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.
I know that using column = NULL in an SQL statement´s WHERE clause results in an empty result set.
As this is very inefficient in programming environments, I´m searching for a way to let MySQL interpret column = NULL like column IS NULL, maybe by setting an SQL mode?
You can use <=> instead. I wouldn't though. This is not portable.
(Thanks to Martin Smith who pointed me to this which was a solution to my problem)
You can have a case statement in your WHERE clause to use the correct syntax:
http://www.postgresql.org/docs/9.4/static/functions-conditional.html
SELECT * FROM my_items WHERE
CASE WHEN 1=1 THEN mac = '08:00:2b:01:02:03'
WHEN 1=2 THEN mac IS NULL
END;
Obviously, the first case (WHEN 1=1) will always be called in this example. You can put your own logic in that satisfies your condition.
Well, at least PostgreSQL does have a parameter for that
transform_null_equals = true
When is set to true, the query parser will transform
field = NULL
to
field is NULL
beforehand. Something tells me there's an equivalent parameter hidden in MySQL less documented params.
EDIT as of 2020-07-15
My "not really a solution" might be one of my first answers at SO. I'm somewhat ashamed for answering something about another DBRMS engine instead of what I was asked by the OP.
Anyway, the correct answer would be using the <=> operator as others have said in their answers already. You replace = for that and it will behave as other comparisons:
A = B // zero if different, one if equals, this is treated as a boolean result
A != NULL // always null, therefore not false nor true.
A <=> B // zero if different, one if equals, zero is one of the variables are null, 1 if both are.
This is not a setting and therefore it's behavior would never be session-wise or DDBB wise.
In an MS Access datasheet, is it possible to filter those records whose value is null or empty in a specific field in my table?
Yes.
WHERE myCol IS NULL OR LEN(myCol) = 0
In your SQL statement:
WHERE Nz(CompanyName, '') = ''
In your form's filter property:
Nz(CompanyName, '') = ''
The solution posted by Mitch Wheat will also work. I'm not certain which one will offer the best performance. If you are using Mitch's solution and you are also using other conditions in your Where clause, don't forget to insert parenthesis like this:
WHERE (myCol IS NULL OR LEN(myCol) = 0) AND myCol2 = True
Using a function in the criterion means you can't use the indexes. #Mitch Wheat's solution will use the index for the Is Null test, but not for the Len() test.
A sargable WHERE clause would be this:
WHERE myCol Is Null OR myCol = ""
But I'd recommend turning off "allow zero-length strings" and then you need only do the Null test, which on an indexed field will be extremely fast.
For what it's worth, I find it extremely annoying that MS changed the defaults for new text fields to have Allow ZLS turned on. It means that I have to change every one of them when I'm using the table designer to create new fields.