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

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.

Related

Anylogic: Write parameter value into Database table

I'm trying to write the value of a parameter in Anylogic into a specific cell of a Database table. The parameter is declared in my main and gets its value through a specific calculation in function. Now I want to store the calculated value in the Database table.
I tried using the
INSERT INTO query (executeStatement("INSERT INTO eu (country, capital) VALUES ('Croatia', 'Zagreb')"); --> example from help)
…but I'm not able to use the specific parameter in the query/as a VALUE. I can only write direct input (like 'Croatia'), but not the parameter. At the end I want the table to get the current value from the parameter and insert the value in the table.
I found an Insert connectivity tool in the help function, but unfortunately it's only available in the professional edition.
Does anyone have an idea how to handle this?
Thank you and have a great weekend!
I don't know if I fully understood what you need but if what you want to do is simply insert values into a table, then what you've done inside your "executeStatement" is actually enough:
INSERT INTO eu (country, capital) VALUES ('Croatia', 'Zagreb')
If what you mean by "specific cell" is actually replacing the content of an existing field in a given row, you want to use UPDATE instead:
UPDATE eu SET country='New country', capital='New capital' WHERE <some criteria matching targeted row>
WARNING: don't forget the WHERE statement or every row of your table will be clobbered with these same new values.
And if what you want to do is inserting one or more new rows filled with something that already exists in the database, then you can construct your dataset directly from a SELECT query:
INSERT INTO eu (country, capital)
SELECT country_field, capital_field
FROM some_table
WHERE some_criteria
The SELECT query following the UPDATE statement can be absolutely anything. It may also refer to the same table if needed. The only requirement is to form rows that have the same structure and same type (at least compatible) than the targeted fields.
You need to adjust your String that defines the SQL statement.
Instead of
"INSERT INTO eu (country, capital) VALUES ('Croatia', 'Zagreb')"
you write
"INSERT INTO eu (country, capital) VALUES ('"+myParam1+", '"+myParam2+"')"
Assuming you have 2 params of type String that hold string text.
Your dbase column type must match the parameter (or variable) type you want to write
Be VERY careful with the ' and " signs as above

How to insert rows in SQLite using default values?

Update:
Here is what I have learned from the answers below...
SQLite supports defining default values on columns. However, it does not support any form of DEFAULT keyword or function in queries. So, in effect, it is not possible to do a MySQL style bulk insert where a column is set explicitly in some rows, and the column default is used in other rows.
There are several creative workarounds listed below, but for simplicity's sake I most prefer Shawn's suggestion of using an INSERT statement per row, possibly all wrapped inside a BEGIN TRANSACTION statement. Only this will allow you to utilize column defaults.
Original Question:
I have a simple SQLite table named todo with this schema...
I can insert rows into this table with this syntax...
INSERT INTO 'todo' ('title', 'complete', 'notes') VALUES
('Pickup dry cleaning', true, 'They close at 7pm'),
('Clean apartment', false, 'Floors have already been swept'),
('Finish homework', true, 'Chapters 3 and 4');
However,
I can't figure out how to omit certain values and let the database use the default for that column.
For example, the complete column has a default of 0. It would be nice to be able to pass undefined as one of the values in my query, thus signaling to SQLite that I'd like to use whatever the column default is, but I get a Result: no such column: undefined error when I try this.
null would not work in this case either, because sometimes you want to explicitly set the value of a cell to null. You can't just plain omit the value either because the parameters are positional.
You just leave it out of the columns being inserted:
INSERT INTO todo(title, notes) VALUES ('Music practice', 'Not Elvis');
I can't figure out how to omit certain values and let the database use the default for that column.
As of this writing, SQLite does not support the default(_) function, but you could use triggers to achieve the effect you want, though doing so is a bit cumbersome.
Here's an example:
CREATE TRIGGER IF NOT EXISTS onnull
AFTER INSERT ON mytable
FOR EACH ROW
WHEN NEW.column = 'undefined'
BEGIN
UPDATE mytable
SET column = 'mydefault' ;
END;
this works if you are using better-sqlite3, and I think it will equally work for sqlite3.
db.prepare("INSERT INTO bugs (title, notes) VALUES (?, ?)").run(["Good Book", "nice test"]);
What Shawn said plus the bulk issue can be solved with DEFAULT value, that is if you are inserting all records manually, if you want it dynamically through a loop for example you must declare a variable as default and change to the specific value if the specific value exists, and use this variable in the query.
String var='DEFAULT';
if (Value exists) {var=Value;}
sql=inset into x(x,y,z) values (a,b,var);

how to insert values to a new column in SQL when other columns are defined as not null?

i have created a table with 3 columns in which 2 are defined as NOT NULL in SQL, now i created a new column i wanted to insert values to only the new variable, but i'm having an error while using Insert into statement
If you are using MySQL, here is your answer:
Inserting NULL into a column that has been declared NOT NULL. For multiple-row INSERT statements or INSERT INTO ... SELECT statements, the column is set to the implicit default value for the column data type. This is 0 for numeric types, the empty string ('') for string types, and the “zero” value for date and time types. INSERT INTO ... SELECT statements are handled the same way as multiple-row inserts because the server does not examine the result set from the SELECT to see whether it returns a single row. (For a single-row INSERT, no warning occurs when NULL is inserted into a NOT NULL column. Instead, the statement fails with an error.)
The documentation is here: MySQL 5.7 Reference Manual: Insert
As said above, just use ' ' and 0 depending on the type of column you have. I believe it's the same for any other DBMS system anyone could use.
Disregarding that this normally indicates you should rethink your database design, some database engines will let you do this through temporary schema manipulation (removing and afterwards re-adding the 'not null' constraint).
Alternatively you could either define default values for the not null columns, or pass in through the insert command the appropriate "default" values, or select a database mode where either the checks are not enforced (thus allowing nulls) or default values are automatically generated (eg mysql in non strict mode which replaces the nulls with a calculated default value).
The only valid use case I can think of is replicating the situation where a database has rows with nulls in certain fields, and then the schema is changed to make those columns not null. Mysql for instance will allow you to add 'not null' constraints to columns that already have data with nulls in that column.

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;

Forcing a datatype in MS Access make table query

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.