views:

604

answers:

4

I have a query in MS Access which creates a table from two subqueries. For two of the columns being created, I'm dividing one column from the first subquery into a column from the second subquery.

The datatype of the first column is a double; the datatype of the second column is decimal, with scale of 2, but I want the second column to be a double as well.

Is there a way to force the datatype when creating a table through a standard make-table Access query?

A: 

You can use CDbl around the columns.

astander
Isn't @onedayone correct that CDbl() won't handle Nulls, so you need to handle it, as he's suggested?
David-W-Fenton
Then you could use NZ, not just iif. So use CDbl(NZ(ColVal,0))
astander
Nz() is inferior to my IIF(..IS NULL..) construct: it causes a syntax error when used outside of the Access UI. Also, the data typing gets weird because Nz() in SQL code coerces the result to text. More more details, see http://allenbrowne.com/QueryPerfIssue.html. In this case, though, wrapping it in the CDBL() function 'merely' creates a performance issue.
onedaywhen
@David W. Fenton: if you indeed believe @oneday*when* be to correct, why didn't you up-vote the answer? It's your community duty :)
onedaywhen
From your link : The Nz() function replaces Null with another value (usually a zero for numbers, or a zero-length string for text.) The new value is a Variant data type, and VBA tags it with a subtype: String, Long, Double, Date, or whatever.
astander
I didn't upvote your answer because I don't consider it the best answer. Even using CDbl doesn't fix all the problems with MakeTable queries, as you still lack full control over text fields and indexing (and just try doing one with an outer join having all Null values in any of the fields on the outer join side and see what you get). The best solution is creating the table ahead of time, and that got my vote.
David-W-Fenton
@onedaywhen: while it's good to have the caveat about Nz() not working from outside Access, it's really a tangential issue when the question is about doing this from *within* Access.
David-W-Fenton
@David W. Fenton: depends what you mean by "within Access". I can't see anything in the question that suggests the OP is using anything but the Access Database Engine.
onedaywhen
@astander: ...and it goes on to say that when used in SQL the engine coerces the result to 'text'. The article concludes that IIF(..IS NULL..) construct is to be preferred over the Nz() function.
onedaywhen
"I have created a query in MS-Access" seems pretty definitive to me -- the OP is using the Access UI to manipulate data. There is no mention of ASP or PHP or any other environment in which this SQL is going to be used. So, your caveats about Nz() are valuable, but entirely tangential to the question being asked, and thus not worthy of my upvote.
David-W-Fenton
@David W. Fenton: "'I have created a query in MS-Access' seems pretty definitive to me" -- maybe but I get the impression you generally only see what you want to see. Methinks in this case you extrapolate too far. Back in the old days, when Jet was a valid DBMS for a VB application, many devs used MS Access as a 'SQL Management Studio' to create persisted database objects: tables, FKs, VIEWs, etc. So they would have used language such as 'creating queries in MS Access' but using Nz() would have been a mistake.
onedaywhen
@David W. Fenton: Have you read what Allen Browne wrote about Nz() being inferior in SQL code even when the Access UI does apply? I get the impression that Nz() is only really suitable for code using the Access object model e.g. VBA in Forms.
onedaywhen
+3  A: 

One way to do it is to explicitly create the table before putting anything into it.

Your current statement is probably like this:

SELECT Persons.LastName,Orders.OrderNo
INTO Persons_Order_Backup
FROM Persons
INNER JOIN Orders
ON Persons.P_Id=Orders.P_Id
WHERE FirstName = 'Alistair'

But you can also do this:

----Create NewTable
CREATE TABLE NewTable(FirstName VARCHAR(100), LastName VARCHAR(100), Total DOUBLE)
----INSERT INTO NewTableusing SELECT
INSERT INTO NewTable(FirstName, LastName, Total)
SELECT FirstName, LastName, 
FROM Person p
INNER JOIN Orders o
ON p.P_Id = o.P_Id
WHERE p.FirstName = 'Alistair'

This way you have total control over the column types. You can always drop the table later if you need to recreate it.

Rap
I think that's the *only* way to do it, other than altering the data types after the MakeTable runs.
David-W-Fenton
+1  A: 

You can use the cast to FLOAT function CDBL() but, somewhat bizarrely, the Access Database Engine cannot handle the NULL value, so you must handle this yourself e.g.

SELECT first_column, 
       IIF(second_column IS NULL, NULL, CDBL(second_column)) 
          AS second_column_as_float
  INTO Table666
  FROM MyTest;

...but you're going to need to ALTER TABLE to add your keys, constraints, etc. Better to simply CREATE TABLE first then use INSERT INTO..SELECT to populate it.

onedaywhen
A: 

Sorry this is not an answer but more question related to this thread - I've tried doing the above but my SQL is really not that hot and I can't get it to work, is there not a function in Access that will do this?

Thanks, Avalon

AVN
There is no such function. You don't have to use code to do the above, though. You can create the table with a MakeTable query, then alter its data types by hand, via the Access UI, and then use APPEND queries from then on.
David-W-Fenton