I'm sure this is either totally impossible or really easy:
If I'm creating a table and I want one of the columns to have limited options, it seems that I use either the ENUM or SET value type. But I have to define the possible values at that moment. What if I have another table which has two columns, a primary key column and a data column, and I want the ENUM for my new table to be set to the primary key of the already existing column?
I'm sure I can just write in the values long-hand, but ideally what I need is for new values to be entered into the list table and for the table with the enum column to just accept that the value choices will include anything new added to that list table.
Is this possible without needing to manipulate the structure of the new table each time something is added to the list?
i think this link help :
http://dev.mysql.com/doc/refman/5.0/en/enum.html
have a discussion of it
in the user comments
start :
"In MySQL 5.0, you can convert an enum's values into a dynamically-defined table of values, which then provides effectively a language-neutral method to handle this kind of conversion (rather than relying on PHP, Tcl, C, C++, Java, etc. specific code).
"
he do it with stored PROCEDURE
The easiest way is to use a regular column without contraints. If you're interested in all the current values, use DISTINCT to query them:
select distinct YourColumn from YourTable
That way, you don't have any maintenance and can store whatever you like in the table.
The foreign key table you mention is also a good option. The foreign key will limit the original column. Before you do the actual insert, you run a query to expand the "enum" table:
insert into EnumTable (name)
select 'NewEnumValue'
where not exists (select * from EnumTable where name = 'NewEnumValue')
Not sure what exactly you're trying to achieve btw; limit the column, but automatically expand the choices when someone breaks the limit?
Related
Can I create a generated column in table A which sums up a column in table B with a tableA_id of the row in table A?
Suppose I have a table of of families, and a table of children. I want a sum of the ages of the children for each family.
ALTER TABLE people.families
ADD COLUMN sumofages DECIMAL(10,2) GENERATED ALWAYS AS
(SELECT SUM(age) FROM people.children WHERE family_id = people.families.id) STORED;
ERROR 3102: Expression of generated column 'sumofages' contains a disallowed function.
I can't save it as type VIRTUAL either. What am I doing wrong here?
ALTER TABLE people.families
ADD COLUMN sumofages DECIMAL(10,2) GENERATED ALWAYS AS
(SELECT SUM(age) FROM people.children WHERE family_id = people.families.id) VIRTUAL;
ERROR 3102: Expression of generated column 'sumofages' contains a disallowed function.
I don't know which function is disallowed. SUM doesn't seem to be it. Maybe SELECT?
https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
Generated column expressions must adhere to the following rules. An
error occurs if an expression contains disallowed constructs.
Subqueries, parameters, variables, stored functions, and user-defined
functions are not permitted.
It's reasonable that the expression for a generated column can reference only columns within the same row. The generated column cannot use subqueries, or reference other tables, or functions with non-deterministic output.
Suppose generated columns did support cross-table references. Particularly consider the case of STORED generated columns.
If you update a table, MySQL would also have to update any references in generated columns elsewhere in the database, if they reference the row you updated. It would be complex and expensive for MySQL to track down all those references.
Then consider add indirect references through stored functions.
Then consider that your update is to an InnoDB table in a transaction, but the generated column may be in a non-transaction (MyISAM, MEMORY, ARCHIVE, etc.) table. Should your update be reflected in those generated columns when you make it? What if you roll back? Should your update be reflected at the time you commit? Then how should MySQL "queue up" changes to apply to those tables? What if multiple transactions commit updates that affect the generated column reference? Which one should win, the one that applied the change last or the one that committed last?
For these reasons, it's not practical or efficient to allow generated columns to reference anything other than the columns of the same row in the same table.
The idea of a computed column is to derive data from the other columns in the record, e.g. combine the country code with the zip code, so you'd store DE and 12345 and you'd get DE-12345 which you could use in an address.
What you are trying to do, however, is something completely different. You are accessing data from another table. But that table's data may change, so when accessing the same record you might suddenly get a completely different result. Computed columns should contain deterministic values, so they don't change as long as your record's data doesn't change. I don't know about MySQL in this regard, but it probably forbids non-deterministic data, such as your subquery.
What you are actually looking for is a view. A view can combine selects from different tables, just as you want it to happen. So use
create view familydata as
(
select f.*, sum(c.age) as sumofages
from families f
join children c on c.family_id = f.id
group by f.id
);
or
create view familydata as
(
select f.*,
(
select sum(age)
from children c
where c.family_id = f.id
) as sumofages
from families f
);
I hope I got the syntax right.
Is there any way to issue a mysql statement to create a table without having to assign the number of columns? I am working with the MySQL C API for grabbing some variables and then storing them in a table. The issue that I am encountering is that I have to create the table (obviously) before inserting the variables into the table. These variables sometimes are structures (two, three or four variables into a single table), so I am looking for a way of not having to say:
CREATE TABLE Structures(ID varchar(10) primary key, name varchar(25))
but creating a table on where any number of columns can be inserted?
Let me know if I am being a bit vague in here.
No, you can't. You can however add columns at runtime using ALTER TABLE.
However, personally, I wouldn't recommend that. You should know what your database looks like, before you start implementing it.
The other way to code this is to use two tables and a one-to-many between them.
For instance, you might have a tables like this - pcode,
table experiment
experiment_id: long
experiment_header: varchar(50)
table experiemnt_data
experiemnt_data_id: long
experiment_id: long
key: varchar(20)
value: long
#id = insert into experiment (experiment_header) value("test run")
insert into experiment_data (experiment_id, key, value) value(#id, 'x', 1)
insert into experiment_data (experiment_id, key, value) value(#id, 'y', 20)
AS #Mark and #attis said:
You can't. You can however add columns at runtime using ALTER
TABLE.
However, personally, I wouldn't recommend that. You should know what
your database looks like, before you start implementing it.
I think the best solution could be:
Create two tables :
column with (id, name)
values with (id, column_id, value)
then you just have to join them to easily get you results, and you can easily add others "columns"
You can also store everything in values table, but your data may be inconsistent, and, in my mind, it's faster to look for a number than to compare strings (table lock, index etc...)
I wanted to comment #Mark post, but can't (reputation too low)
I'm pretty new to MS Access 2007, and I wanted to ask about something, that I couldn't find.
Is it possible that in a specific column, say for example: type, to make the only possible values "typea", "typeb"?
Just like the yes/no available option, just that it will contain my own specific values.
Yes you can create a lookup table with the id and description (typea/typeb) values in and then reference this table. You can add a check constraint on the column to ensure the type entered matches the constraint specified. (typea or typeb).
There is a way that involves only the basics. Create a reference table for the valid values of Type. It might have two columns, Id and Description. The primary key is Id.
Put two rows in with Id values of "typea" and "typeb". Put whatever you want for the description. You might use this later.
Use the relationship tool to make the column in your existing table reference the Id column in the types table. This will create a references constraint in the database.
Another response suggested adding a check constraint. That will probably run faster, but may involve more learning on your part.
And, if you ever add a third and fourth type, having a table like the one I've given will make it super easy to modify.
I'm using Spring (Roo specifically) to develop an application and for one entity I have a drop down list that is based on a set of enums (i.e. enum(Blue,Pink,Red)). When stored in MYSQL database these enums are stored as numbers (obviously). I want these to be stored as the actual string values instead of numbers in the database (so in MYSQL I want "pinK" to be under "color" instead of simply "2".Is this possible? Thanks
edit:
Let me try asking it a different way. Say when I'm retrieving the data from MYSQL. Instead of the symbolic values I want the actual words is there any way to do this?
I'd try labeling your field with #Enumerated(EnumType.STRING) annotation like:
#Enumerated(EnumType.STRING)
private MyEnumType myEnumField;
You can store the values as text, then use an insert trigger to validate that the stored values are one of the allowed values (since MySQL doesn't support check constraints).
You can also index the minimum number of characters to provide uniqueness, to make your indexing overhead smaller. In your example, you'd only need to index the first character, since 'B', 'P', and 'R' are unique. If you add 'Brown' to the list, you'll need to index the first two characters ('Bl','Pi','Re','Br').
EDIT
My original suggestion was to store the values as their actual text representations, rather than as a number.
Another way to do what you're asking, though, is to add a 'colors' table:
id INT
name VARCHAR
Then have your 'enum' column be a foreign key to the colors table. Then when you do your select:
SELECT ...,colors.name AS color
FROM table t
JOIN colors c ON t.color = c.id
Hello I need to add a column to a table in SQL Server 2008. If I use the script below:
ALTER TABLE SampleTable ADD SampleColumn bigint NULL
it adds the column at the end of the table. What if I want the column at a position in the table using script only. For some reasons which are hard to explain, I cannot drop table and execute a new create table script.
Any ideas and suggestions!
Column order is irrelevant.
Observe:
SELECT Col1, Col2, Col3
FROM Table
SELECT Col3, Col2, Col1
FROM Table
Column order only matters if you use SELECT * which is another reason not to do that.
Besides recreating the table, there is no way to change the default column order in the metadata.
If you need a workaround, it's possible to create a VIEW that selects the fields in the desired order and use that.
If you can use SSMS, then it's easy -- just "design" your table (r-click the table), add your column, then drag it up/down in the list wherever you want it.
That said -- if you view the change script for doing this (i.e., all of the TSQL behind that simple drag & drop), there is an awful lot that actually goes on automagically (including re-creating of the table).
I know column order DOES matter (sorry #JNK) for someone who likes to follow a standard organizational method (like having all of your foriegn keys toward the top, etc.), or someone supporting queries/procedures that don't specify columns (like you can do with insert statements, or selects based on position).
There isn't another way to insert a column in a SQL Server table "in between" existing columns - you need to build a temp table and rebuild the old table. That said, column order shouldn't matter - are you sure that the column needs to be inserted in order?
Likely your best bet is to just use the GUI, script it out, and then change the constraint name to something reasonable within the script. You're right that the numerical constraint name isn't ideal, and it's not a best practice to allow SQL Server to determine your object names.
check the below link for more:
stackoverflow.com/questions/965927/inserting-column-between-other-columns-in-sql-server-using-script