Forcing a datatype in MS Access make table query - sql

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?

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.

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.

You can use CDbl around the columns.

An easy way to do this is to create an empty table with the correct field types and then to an Append-To query and Access will automatically convert the data to the destination field.

I had a similar situation, but I had a make-table query creating a field with NUMERIC datatype that I wanted to be short text.
What I did (and I got the idea from Stack) is to create the table with the field in question as Short Text, and at the same time build a delete query to scrub the records. I think it's funny that a DELETE query in access doesn't delete the table, just the records in it - I guess you have to use a DROP TABLE function for that, to purge a table...
Then, I converted my make-table query to an APPEND query, which I'd never done before... and I just added the running of the DELETE query to my process.
Thank you, Stack Overflow !
Steve

I add a '& ""' to the field I want to make sure are stored as text, and a ' *1 ' (as in multiplying the amount by 1) to the fields I want to store as numeric.
Seems to do the trick.

To get an Access query to create a table with three numeric output fields from input numeric fields, (it kept wanting to make the output fields text fields), had to combine several of the above suggestions. Pre-establish an empty output table with pre-defined output fields as integer, double and double. In the append query itself, multiply the numeric fields by one. It worked. Finally.

Related

How can I pull off an INSERT, SELECT, JOIN, and CAST query with Microsoft SQL Server Management Studio?

I have been trying to set up a test database but I keep running into issues with pulling in the data from its normalized form.
Below is the latest version of the SQL query I've been working on.
INSERT INTO TestData.dbo.Info (Name,Did)
SELECT DISTINCT a.Name, b.Did
FROM StageDB.dbo.MockData a INNER JOIN Testdata.dbo.Dinfo b
ON a.Name = CAST(b.Did as varchar(10))
The output I get is the following:
(0 row(s) affected)
I've been trying to monkey around with it on my own but can't seem to make it work the way I want to.
My objective here is to pull data (the primary key from a table with data already in my database, Did from TestData.dbo.Dinfo that is of int type) and merge it with data from my staging table (a particular column from the table in the staging database, StageDB.dbo.MockData, Name of type varchar(10)), then inserting into a new table on my main database. The database table I'm trying to put these things into is all set up with the correct fields and types (primary key column, auto generated as rows are added, Name column that is varchar(10), and Did column that is int).
EDIT: Table Definitions, Sample Data, Desired Result
Destination Table:
TestData.dbo.Info
Columns: Iid (int, primary key of table set to auto increment as new records are added), Name (varchar(10)), Did (int, foreign key from TestData.dbo.Dinfo).
StageDB.dbo.MockData
Columns: Many columns exist in this table that are not relevant to what I am trying to pull off. The only one I am interested in is the column containing names that I want to tie together with information from the Dinfo table. Name (nvarchar(255),null).
TestData.dbo.Dinfo
Columns: Did (int, primary key), Donor (varchar(20)).
Sample of Data
From Dinfo:
Did Donor
01 Howard L
From MockData:
Name
Smith J
Desired Results
Iid Name Did
01 Smith J 01
Any help or advice would be much appreciated. I would really like it if someone can show me the correct SQL syntax for this as I think it may just be a matter of writing it correctly. Additionally, any tips or websites that can help me learn more SQL would be appreciated.
Thank you!
Change this:
ON a.Name = b.Did
To this:
ON a.Name = CAST(b.Did as varchar(10))
I suspect there's a lot more wrong with your query in terms of getting the results you want, but this should fix your error.
You need to figure out where the error is occurring. There are three possibilities:
mockdata.name is a string and NInfo.data is an integer
dinfo.did is a string and NInfo.did is an integer
mockdata.name is a string and dinfo.did is an integer (or vice versa)
Based on the naming conventions, the third is the most likely. When a number is compared to a string, the string is converted to a number. However, you need to be careful whenever you use implicit type conversions.
If the third option, then you can convert the integer to a string (as other answers propose). However, I would ask why you are doing such a comparison.
Error is in ON a.Name = b.Did Name column may contains alphabets,number or special characters. Did column contains only number or integers only.

SQL: How to apply a function (stored procedure) within an UPDATE-clause to change values?

the following function deletes all blanks in a text or varchar column and returns the modified text/varchar as an int:
select condense_and_change_to_int(number_as_text_column) from mytable;
This exact query does work.
Though my goal is to apply this function to all rows of a column in order to consistently change its values. How would I do this? Is it possible with the UPDATE-clause, or do i need to do this within a function itself? I tried the following:
UPDATE mytable
SET column_to_be_modiefied = condense_and_change_to_int(column_to_be_modiefied);
Basically i wanted to input the value of the current row, modify it and save it to the column permanantly.
I'd welcome all ideas regarding how to solve scenarios like these. I'm working with postgresql (but welcome also more general solutions).
Is it possible with an update? Well, yes and sort-of.
From your description, the input to the function is a string of some sort. The output is a number. In general, numbers should be assigned to columns with a number type. The assumption is that the column in question is a number.
However, your update should work. The result will be a string representation of the number.
After running the update, you can change the column type, with something like:
alter table mytable alter column column_to_be_modiefied int;

How to concatenate row values for use in WHERE clause of T-SQL query

I want to write a query in T-SQL to perform a search on two concatenated columns. The two columns are fname and lname. Here is what I have so far:
SELECT
fname,
lname,
...
FROM
users
JOIN
othertable ON foo=bar
WHERE
fname+' '+lname LIKE '%query%'
SQL server doesn't like that syntax, though. How do I structure the query so that I can perform a WHERE LIKE operation that searches through two concatenated columns, allowing me to search the user's full name, rather than just first name and last name individually?
I can only suggest that one of fname or lname is NULL so the LIKE fails., (NULL concat anything is null)
Try
...
ISNULL(fname, '') + ' ' + ISNULL(lname, '') LIKE '%query%'
However, I would use a computed column and consider indexing it because this will run awfully.
My suggestion is to add a calculated column to your table for full_name
calculated column examples:
--drop table #test
create table #test (test varchar (10) , test2 varchar (5),[Calc] AS right(test, 3))
Insert #test
values('hello', 'Bye')
Insert #test
values('hello-bye', null)
Alter table #test
add [MyComputedColumn] AS substring(test,charindex('-',test), len(test)),
Concatenatedcolum as test+ ' ' +test2
select * from #test
As you can see you may have to play around a bit until you get the results you want. Do that in a temp table first to avoid having to restructure the database table multiple times. For names, especially if you are using middle name which is often blank, you may need to add some code to handle nulls. You may also need to have code sometimes to cast to the same datatype if one filed you are concatenating is an int for instance and the other a varchar.
I think one of the join conditions might be causing a problem. Try rewriting it, you may find the error goes away ;)

How can I turn a column name into a result value in SQL Server?

I have a table which has essentially boolean values in a legacy database. The column names are stored as string values in another table so I need to match the column names of one table to a string value in another table. I know there has to be a way to do this directly with SQL in SQL Server but it is beyond me.
My initial thought was to use PIVOT but it is not enabled by default and enabling it would likely be a difficult process with pushing that change to the Production database. I would prefer to use what is enabled by default.
I am considering using COALESCE to translate the boolean value to the string that value that I need. This will be a manual process.
I think I will also use a table variable to insert the results of the first query into that variable and use those results to do the second query. I still have the problem that the columns are on a single row so I wish I could easily pivot the values to put the column names in the result set as strings. But if I could easily do that I could easily write the query with a sub-select.
Any tips are welcome.
Checkout Sysobjects and SysColumns in SQL Server. They are 2 SQL tables that gives you the names of the tables in your DB and the names of the columns that go with that table.
The system view INFORMATION_SCHEMA.COLUMNS will also give you what you want.
You can build a SQL string and then execute that string as a query. Not the prettiest by any means but I think it would work the way you want it to. You would just use a cursor or while loop to build the string.
If you're comfortable with .Net you could just write your own stored proc in your language of choice and manipulate the data in code instead.
Heres a link to get started
CLR Stored Procedures
I'm not quite sure I understand how your design is currently put together (could you post an example?), but the information_schema.columns view will give you a table containing all the column names as string values. If you join your second table against that I think you'll probably get what you need.
For Example, i have a table STATEtbl having 3 columns and i want to get all the column names of this table as ROW values... i use the below query
Select SC.name as Columns from Syscolumns SC
Join Sysobjects SO On SC.id = SO.Id
where Object_name(SO.Id) = 'STATEtbl'
Result of the query:
Columns
--------
State
StateCode
StateFullName

MySQL - Set default value for field as a string concatenation function

I have a table that looks a bit like this actors(forename, surname, stage_name);
I want to update stage_name to have a default value of
forename." ".surname
So that
insert into actors(forename, surname) values ('Stack', 'Overflow');
would produce the record
'Stack' 'Overflow' 'Stack Overflow'
Is this possible?
Thanks :)
MySQL does not support computed columns or expressions in the DEFAULT option of a column definition.
You can do this in a trigger (MySQL 5.0 or greater required):
CREATE TRIGGER format_stage_name
BEFORE INSERT ON actors
FOR EACH ROW
BEGIN
SET NEW.stage_name = CONCAT(NEW.forename, ' ', NEW.surname);
END
You may also want to create a similar trigger BEFORE UPDATE.
Watch out for NULL in forename and surname, because concat of a NULL with any other string produces a NULL. Use COALESCE() on each column or on the concatenated string as appropriate.
edit: The following example sets stage_name only if it's NULL. Otherwise you can specify the stage_name in your INSERT statement, and it'll be preserved.
CREATE TRIGGER format_stage_name
BEFORE INSERT ON actors
FOR EACH ROW
BEGIN
IF (NEW.stage_name IS NULL) THEN
SET NEW.stage_name = CONCAT(NEW.forename, ' ', NEW.surname);
END IF;
END
According to 10.1.4. Data Type Default Values no, you can't do that. You can only use a constant or CURRENT_TIMESTAMP.
OTOH if you're pretty up-to-date, you could probably use a trigger to accomplish the same thing.
My first thought is if you have the two values in other fields what is the compelling need for redundantly storing them in a third field? It flies in the face of normalization and efficiency.
If you simply want to store the concatenated value then you can simply create a view (or IMSNHO even better a stored procedure) that concatenates the values into a pseudo actor field and perform your reads from the view/sproc instead of the table directly.
If you absolutely must store the concatenated value you could handle this in two ways:
1) Use a stored procedure to do your inserts instead of straight SQL. This way you can receive the values and construct a value for the field you wish to populate then build the insert statement including a concatenated value for the actors field.
2) So I don't draw too many flames, treat this suggestion with kid gloves. Use only as a last resort. You could hack this behavior by adding a trigger to build the value if it is left null. Generally, triggers are not good. They add unseen cost and interactions to fairly simple interactions. You can, though, use the CREATE TRIGGER to update the actors field after a record is inserted or updated. Here is the reference page.
As of MySQL 8.0.13, you can use DEFAULT clause for a column which can be a literal constant or an expression.
If you want to use an expression then, simply enclose the required expression within parentheses.
(concat(forename," ",surname))
There are two ways to accomplish what you are trying to do as per my knowledge:
(important: consider backing up your table first before running below queries)
1- Drop the column "stage_name" all together and create a new one with DEFAULT constraint.
ALTER TABLE actors ADD COLUMN stage_name VARCHAR(20) DEFAULT (concat(forename," ",surname))
2- This will update newer entries in the column "stage_name" but not the old ones.
ALTER TABLE actors alter stage_name set DEFAULT (concat(forename," ",surname));
After that, if you need to update the previous values in the column "stage_name" then simply run:
UPDATE actors SET stage_name=(concat(forename," ",surname));
I believe this should solve your problem.