how to define integer array as a field when creating new table in mySQL - mysql

how to define integer array as a field when creating new table in mySQL

There is currently no way to store an array of integers in MySQL, so you should implement this by yourself. You could choose one of a few things, these two approaches included:
serialise the data with a separator (e.g. LONGTEXT: 123|4|65|864)
pack the integers into a blob (e.g. LONGBLOB: 0x0000007b000000040000004100000360)

You can't. You could do something like convert your array to a comma-separated string, and store this. Or you could define a normalised table structure and have each integer in it's own row. Each row for a given array would also contain some kind of array key as a separate field. This also has the advantage that you can easily query for individual array elements.
Edit In my view the first option is not very elegant. Unless you define your field as TEXT you're going to have issues with varying string lengths, and defining your field as VARCHAR(10000) or whatever is not very efficient. Certainly if your array lengths are long you should consider a normalised solution.

Related

Store and query array or group of words in MYSQL and PHP

I am working on a project that uses PHP/MYSQL as the backend for an IOS app that makes a lot of use of dictionaries and arrays containing text or strings.
I need to store this text in MYSQL (coming from Arrays of srtrings on phone) and then query to see the text contains (case insensitive) a word or phrase in question.
For example, if the array consists of {Ford, Chevy, Toyota, BMW, Buick}, I might want to query it to see it contains Saab.
I know storing arrays in a field is not MYSQL friendly as it prevents optimization. However, it would be way too complicated to create individual tables for these collections of words which are created by users.
So I'm looking for a reasonable way to store them, perhaps delimited with spaces or with commas that makes possible reasonably efficient searches.
If they are stored separated by spaces, I gather you can do something with regex like:
SELECT
*
FROM
`wordgroups`
WHERE
wordgroup regexp '(^|[[:space:]])BLA([[:space:]]|$)';
But this seems funky.
Is there a better way to do this? Thanks for any insights
Consider using a FULLTEXT index. And use MATCH(...) AGAINST(... IN NATURAL LANGUAGE MODE).
FULLTEXT is very fast for "words", and IN NATURAL MODE may solve your Saab example.
Using regexp can achieve what you want, however, your query will be inefficient, since it cannot rely on any indexes.
If you want to store a list of words and their position within the array does not matter, then you may consider storing them in a single field, space delimited. But instead of using a regexp, use fulltext indexing and searching. This method has a clear advantage over searching with regexp: it uses an index. It has some drawbacks as well: there is a stopword list (these are excluded from searching) and there is a minimum word length as well. The good news is that these parameters are configurable. Also, you get all the drawbacks of storing data in a delimited field, as detailed in Is storing a delimited list in a database column really that bad? question here on SO.
However, if you want to use dictionaries (key - value pairs) or the position within the list may be important, then the above data structure will not do.
In this case, I would consider if mysql is the right choice for storing my data in the first place. If you have multi-dimensional lists, or lists containing lists, then I would definitely choose a different nosql solution.
If you only need simple, two-dimensional lists / dictionaries, then you can store all of them in a single table with a similar structure as below:
list_id - unique identifier of the list, primary key
user_id - id of the user the list belongs to
key - for dictionaries this is the lookup field (indexed), for other lists it may store the position of the element. String data type.
value - the field holding the value (indexed). Data type should be string, so that it could hold different data types as well.
A search to determine if a list holds a certain value would be fast and efficient lookup using the index on either the key or value fields.

properties table pattern vs storing all properties in json column [duplicate]

This question already has answers here:
When can I save JSON or XML data in an SQL Table
(8 answers)
Storing JSON in database vs. having a new column for each key
(10 answers)
Closed 3 years ago.
I'd like some feedback on having all properties a model can have in a properties table accessed via relationship (using laravel relationships) vs storing all properties/settings in the same table but in a json column.
Currently, my application has a propeties table called settings that is also polymorphic in nature so multiple models can store their properties there. This table has columns like
key (string),
value(string),
type (string) - tells if the value is of string, integer, boolean, json type
so that I do not send strings to javascript frontend, but instead I can send string, integer, boolean native types for better handling of types in frontend. I do this conversion before I send the properties to the frontend using php function that cast string values to int, boolean, json or string, depending on the type.
This means if a model has 40 properties, all get stored in its own row, so creating one model leads to creating 40 rows that store all properties it may have.
Now the above approach vs approach where I just have a single json column, we can call it settings and I dump all these 40 properties there.
What do I win with json column approach? I shave off a table and I shave off an extra relationship that I need to load on this model each time I do some queries. I also shave off having to each time I get properties cast them to integer, boolean, json or string. (remember the type column above) To keep in mind these properties do not need to be searchable, I need them only for reading from them. I will never use them in queries to return posts based on these properties.
Which one is a better idea to use, I'm building a CMS btw you can see it in action here:
https://www.youtube.com/watch?v=pCjZpwH88Z0
As long as you don't try to use the properties for searching or sorting, there's not much difference.
As you said, putting a JSON column in your model table allows you to avoid a JOIN to the properties table.
I think your properties table actually needs to have one more column, to name the property. So it should be:
key (string),
property (string),
value(string),
type (string) - tells if the value is of string, integer, boolean, json type
The downsides are pretty similar for both solutions.
Queries will be more complex with either solution, compared to querying normal columns.
Storing non-string values as strings is inefficient. It takes more space to store a numeric or datetime value as a string than as a native data type.
You can't apply constraints to the properties. No way to make a property mandatory (you would use NOT NULL for a normal column). No way to enforce uniqueness or foreign key references.
There's one case I can think of that gives JSON an advantage. If one of your custom properties is itself multi-valued, there's a straightforward way to represent this in JSON: as an array within your JSON document. But if you try to use a property table, do you store multiple rows for the one property? Or serialize the set of values into an array on one row? Both solutions feel pretty janky.
Because the "schemaless properties" pattern breaks rules of relational database design anyway, there's not much you can do to "do it right." You're choosing the lesser of two evils, so you can feel free to use the solution that makes your code more convenient.

Storing attributes with multiple integer values

I need to store a dynamic number of integer attributes (1-8). I'm storing them in individual columns in the database table, like:
attribute_1, attribute_2, ..., attribute_8
This makes for a fairly messy model when methods need to reference these, as well as an unwieldy database table and schema.
These are assigned default values (but are overridable on a form), and represent unique identifiers for the user.
For instance, a Brew is composed of up to eight batches before they are mixed together in a fermenter. The brewer might want to go back and refer to any one of these by its unique identifying number. I'm assigning these unique values based on the last highest value when creating a new Brew. However, the user may want to override these default values to some other numbers.
In most cases (smaller breweries), they'll probably only use the first two, but some larger breweries would use all eight.
There must be a better way to store these than having eight different attributes with the same name and a number at the end.
I'm using MySQL. Is there an easy/concise way to store an array or a JSON hash but still be able to edit these values on a form?
I would not store attributes like that. It will limit you in the future. Let say you want to know which brews have used attribute_4? You will have to scan the entire brews table, open the attributes field and deconstruct it to see if 4 is in there.
Much better to separate Brew and Attributes in two tables, and link them, like so:
Another benefit, is you can add attributes easily.
Storing JSON is ok, like #max pointed out. I just propose the normalized database way of doing it.

Set Data Type in mySQL

My knowledge of relational databases is more limited, but is there a SQL command that can be used to create a column that contains a set in each row?
I am trying to create a table with 2 columns. 1 for specific IDs and a 2nd for sets that correspond to these IDs.
I read about
http://dev.mysql.com/doc/refman/5.1/en/set.html
However, the set data type requires that you know what items may be in your set. However, I just want there to be a variable-number list of items that don't repeat.
It would be much better to create that list of items as multiple rows in a second table. Then you could have as many items in the list you want, you could sort them, search for a specific item, make sure they're unique, etc.
See also my answer to Is storing a delimited list in a database column really that bad?
No, there's no MySQL data type for arbitrary sets. You can use a string containing a comma-delimited list; there are functions like FIND_IN_SET() that will operate on such values.
But this is poor database design. If you have an open-ended list, you should store it in a table with one row per value. This will allow them to be indexed, making searching faster.
MySQL doesn't support arrays, lists or other data structures like that. It does however support strings so use that and FIND_IN_SET() function:
http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_find-in-set
"SET" data type won't be a good choice here.
You can use the "VARCHAR" and store the values in CSV format. You handle them at application level.
Example: INSERT into my_table(id, myset) values(1, "3,4,7");

Optimal Way to Store/Retrieve Array in Table

I currently have a table in MySQL that stores values normally, but I want to add a field to that table that stores an array of values, such as cities. Should I simply store that array as a CSV? Each row will need it's own array, so I feel uneasy about making a new table and inserting 2-5 rows for each row inserted in the previous table.
I feel like this situation should have a name, I just can't think of it :)
Edit
number of elements - 2-5 (a selection from a dynamic list of cities, the array references the list, which is a table)
This field would not need to be searchable, simply retrieved alongside other data.
The "right" way would be to have another table that holds each value but since you don't want to go that route a delimited list should work. Just make sure that you pick a delimiter that won't show up in the data. You can also store the data as XML depending on how you plan on interacting with the data this may be a better route.
I would go with the idea of a field containing your comma (or other logical delimiter) separated values. Just make sure that your field is going to be big enough to hold your maximum array size. Then when you pull the field out, it should be easy to perform an explode() on the long string using your delimiter, which will then immediately populate your array in the code.
Maybe the word you're looking for is "normalize". As in, move the array to a separate table, linked to the first by means of a key. This offers several advantages:
The array size can grow almost indefinitely
Efficient storage
Ability to search for values in the array without having to use "like"
Of course, the decision of whether to normalize this data depends on many factors that you haven't mentioned, like the number of elements, whether or not the number is fixed, whether the elements need to be searchable, etc.
Is your application PHP? It might be worth investigating the functions serialize and unserialize.
These two functions allow you to easily store an array in the database, then recreate that array at a later time.
As others have mentioned, another table is the proper way to go.
But if you really don't want to do that(?), assuming you're using PHP with MySQL, why not use the serialize() and store a serialized value?