Archive for January, 2013
MySQL Auto Increment
Somebody ran into a problem after reading about the MySQL CREATE
statement and the AUTO_INCREMENT
option. They couldn’t get a CREATE
statement to work with an AUTO_INCREMENT
value other than the default of 1. The problem was they were using this incorrect syntax:
CREATE TABLE elvira ( elvira_id int unsigned PRIMARY KEY AUTO_INCREMENT=1001 , movie_title varchar(60)) ENGINE=InnoDB CHARSET=utf8; |
It raises this error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1001 , movie_title varchar(60)) ENGINE=InnoDB CHARSET=utf8' at line 2 |
They concluded that MySQL requires you to assign a default value of 1 as the initial automatic numbering value; then you use the ALTER
statement to change the initial sequence value. That assumption is incorrect. The problem was with their assignment of an overriding AUTO_INCREMENT
value inside the parenthetical list of columns. That assignment needs to occur after the list of columns and constraints, like
CREATE TABLE elvira ( elvira_id int unsigned PRIMARY KEY AUTO_INCREMENT , movie_title varchar(60)) ENGINE=InnoDB AUTO_INCREMENT=1001 CHARSET=utf8; |
It’s not an unlikely mistake since there’s no clear example on either of the referenced web pages (at the time of writing). It would be nice if they were added but I’m of the opinion some of the reference manual pages are too sparse.
After creating the table, you have the generic fix that seems to appear most often as an answer to setting or re-setting the auto numbering sequence of a MySQL table:
ALTER TABLE elvira AUTO_INCREMENT=1001; |
Why would you set the auto numbering sequence to something other than 1? Some designers consider it a best practice to increment from a set point like 101 or 1,001 for your Application Programming Interface (API) and they leave a readily identifiable sequence number set for pre- or post-seeded data in tables. The region of preallocated numbers are typically only used in a few of the tables, in any application, but consistently managing sequences across all tables does sometimes simplifies data diagnostics.
Hope this helps somebody looking for a syntax fix. By the way, you can find it on Page 162 of the Oracle Database 11g & MySQL 5.6 Developer Handbook.
Excel: Navigate a range
Somebody posted a comment on my Excel UDF Tutorial, and on reflection it appears he’d like to navigate a range in VBA. While I don’t see a purpose in that because it duplicates either the VLOOKUP
or HLOOKUP
function (depending on whether you’re navigating a column or row).
Anyway, here’s how you’d do it in VBA:
Function Finding(lookupWord As String, lookupRange As Range, lookupColumn As Integer) As Integer ' Define variables. Dim lookupIndex As Integer Dim lookupMax As Integer Dim returnValue As Integer ' Assign values to variables. lookupIndex = 1 lookupMax = lookupRange.Rows.Count returnValue = 1 ' Print starting and ending index values. MsgBox ("[" + CStr(lookupIndex) + "][" + CStr(lookupMax) + "]") ' Loop until found, but exit when not found. Do Until lookupRange.Cells(lookupIndex, 1).Value = lookupWord ' Print diagnostic value to determine what's evaluated. MsgBox ("[" + CStr(lookupIndex) + "] [" + CStr(lookupRange.Cells(lookupIndex, 1).Value) + "]") ' Fail safe exit when no matching value is found. If lookupIndex = (lookupMax + 1) Then ' Assign a 0 (zero) as a false return flag value. returnValue = 0 Exit Do End If ' Increment counting index value. lookupIndex = lookupIndex + 1 Loop 'Return a 1 when the value is found and zero when it isn't. Finding = returnValue End Function |
I only chose a DO UNTIL
loop because that was in the comment. It would be more appropriate to, from my perspective, use a FOR
range loop, like this:
For lookupIndex = 1 To lookupMax ' Loop contents. Next lookupIndex |
Hope this helps.
Excel: How-to-use SUMIF
Debbie asked a question about why a comparison wasn’t working in the Microsoft Excel SUMIF
function when the initial array value was empty. This post answers that question.
The SUMIF
function takes a lookup range, which anticipates a one column with a lookup value and another column with a value. The SUMIFS
function works along the same line but accepts multiple lookups against a series of lookup list columns.
This shows a simple model of the SUMIF
function:
The formula in cell G3
is:
=SUMIF(B$3:B$5,"<"&$E$3,C$3:C$5) |
If you left off the $ symbol and made the comparison "<"&E3
, you could add the sums for any number of values that are less than a value in the same row (or counting index with named ranges). You could also make the inequality symbol a parameter with this modified formula:
=SUMIF(B$3:B$5,$E$5&$E$3,C$3:C$5) |
Now, your analysis model lets you choose whether you want to look for the sum greater than or less than a specific number in the lookup range. Named ranges compare index values between the lookup range and comparison range values, which allows them to be in different rows or spreadsheets. The only problem is that the label has an inverted inequality sign. You can fix that by constantly editing the description or by simply replace the text of the label with a dynamic text string, like this:
=CONCATENATE("Comparison """,$E$5,""" Value") |
After applying the fix to the label, it looks like:
When the lookup column contains all nulls, the same formula returns a zero, as shown in the illustration.
You'll also get an error flag, unless you unchecked the Flag formulas that refer to empty cells in the error checking options. The IFERROR
function can't be used to suppress this type of error.
Why doesn't the error return a null value? That's because an equality operator compares values in the array against a static or dynamic lookup value. While equality operators don't implicit cast values for comparison, they also don't compare null values. Only the ISBLANK
function lets you find an empty cell and it can't be used inside a SUMIF
function call.