How to properly get flag value from database using PHP? - php

Imagine it like this. There is a field in my database called flags in which are added or removed data like this:
UPDATE people SET flags=flags|16 WHERE ....
UPDATE people SET flags=flags|128 WHERE ....
UPDATE people SET flags=flags&~16 WHERE ....
UPDATE people SET flags=flags&~128 WHERE ....
For instance this field can have value like 65536 or more or less. My question is - How to get specific flag from this field using PHP code? I mean something like this:
SELECT * FROM people WHERE flags=16;
But the result will return all people with not just number 16 in field but it will return people with flag 65536, people with 16 but not people with 2 or 1. Which SELECT query should I use here in my php code or maybe some specific PHP integrated functions? Thank you.

Assuming flags is a bitfield and you want to select rows where bit #4 (10000) is set
SELECT * FROM people WHERE flags & 16;
This is not ideal though as you're losing out on all that referential goodness that DBs are good for.
What you should have is two new tables; flags and people_flags. The former contains all the flags (id and name columns should be sufficient). The latter contains flag_id and people_id columns, creating a many-to-many relationship (see junction table).

The logic is not correct though. You cant have just one flag that contains 16 as its not unique.
Lets say you have DB with this rows
name:Jhon tel:012345 email:test#test.com flags:16
name:Mike tel:012344 email:mike#test.com flags:16
name:Sarah tel:012346 email:sarah#test.com flags:2442
to select flags 16 from this table with using Select statement you will get two rows of data you can either use Distinct or get flags to be unique

Related

Understanding DB Design

I wanted to make a database to store examination marks. I was wondering if it is better to have
a table for each subject which will make a single record for a roll number
or
have a marks table which will have multiple records for a roll number for every subject
Since the number of subjects is not fixed, which approach would be better.
For the first method, As the tables would be created using php dynamically, so the table names will become a variable, so that will mean extra sanitisation work,
For the second method, the roll number will have many duplicates
Since I am new to DBMS, so any insight is appreciated.
Here's one good reason to choose the second method over the first. Let's say you want to get all marks for a specific roll number. (Using 1 for example.) With the second method, it's just:
SELECT * FROM marks WHERE roll_number = 1;
With the first method (unless someone else knows a better way to do it), it's:
SELECT * FROM subject_a WHERE roll_number = 1
UNION
SELECT * FROM subject_b WHERE roll_number = 1
UNION
SELECT * FROM subject_c WHERE roll_number = 1
...
and so on, for each one of your unknown number of subject tables.

Different PostgreSQL fields orders in PHP when retrieved from two different servers

I am using CodeIgniter 2.1.3 and PHP 5.4.8, and two PostgreSQL servers (P1 and P2).
I am having a problem with list_fields() function in CodeIgniter. When I retrieve fields from P1 server, fields are in the order that I originally created the table with. However, if I use the exact same codes to retrieve fields from P2 server, fields are in reverse order.
If fields from P1 is array('id', 'name', 'age'),
fields from P2 becomes array('age', 'name', 'id')
I don't think this is CodeIgniter specific problem, but rather general database configuration or PHP problem, because codes are identical.
This is the code that I get fields with.
$fields = $this->db->list_fields("clients");
I have to clarify something. #muistooshort claims in a comment above:
Technically there is no defined order to the columns in a table.
#mu may be thinking of the order or rows, which is arbitrary without ORDER BY.
It is completely incorrect for the order of columns, which is well defined and stored in the column pg_attribute.attnum. It's used in many places, like INSERT without column definition list or SELECT *. It is preserved through a dump / restore cycle and has significant bearing on storage size and performance.
You cannot simply change the order of columns in PostgreSQL, because it has not been implemented, yet. It's deeply wired into the system and hard to change. There is a Postgres Wiki page and it's on the TODO list of the project:
Allow column display reordering by recording a display, storage, and
permanent id for every column?
Find out for your table:
SELECT attname, attnum
FROM pg_attribute
WHERE attrelid = 'myschema.mytable'::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
ORDER BY attnum;
It is unwise to use SELECT * in some contexts, where the columns of the underlying table may change and break your code. It is explicitly wise to use SELECT * in other contexts, where you need all columns (in default order).
As to the primary question
This should not occur. SELECT * returns columns in a well defined order in PostgreSQL. Some middleware must be messing with you.
I suspect you are used to MySQL which allows you to reorder columns post columns post-table creation. PostgreSQL does not let you do this, so when you:
ALTER TABLE foo ADD bar int;
It puts this on the end of the table always and there is no way to change the order.
On PostgreSQL you should not assume that the order of the columns is meaningful because these can differ from server to server based on the order in which the columns were defined.
However the fact that these are reversed is odd to me.
If you want to see the expected order on the db, use:
\d foo
from psql
If these are reversed then the issue is in the db creation (this is my first impression). That's the first thing to look at. If that doesn't show the problem then there is something really odd going on with CodeIgniter.

unused number mysql

How can i get all of the records in a table that are out of
sequence so I know which account numbers I can reuse. I have a range
of account numbers from 50100 to 70100. I need to know which account
numbers are not stored in the table (not currently used) so I can use.
For instance say I have the following data in table:
Account Name
------ --------
50100 Test1
50105 Test2
50106 Test4
..
..
..
I should see the results:
50101
50102
50103
50104
because 50101-50104 are available account numbers since not currently in
table.
copied from http://bytes.com/topic/sql-server/answers/78426-get-all-unused-numbers-range
With respect to MYSQL and PHP.
EDITED
My range is 10000000-99999999.
My present way is using MySql query:
'SELECT FLOOR(10000000 + RAND() * 89999999) AS random_number FROM contacts WHERE "random_number" NOT IN (SELECT uid FROM contacts) LIMIT 1';
Thanks.
solution 1:
Generate a table with all possible accountnumbers in it. Then run a query similar to this:
SELECT id FROM allIDs WHERE id NOT IN (SELECT id FROM accounts)
Solution 2:
Get the whole id colummn into an array in php or java orso. Then run a for-loop to check if the number is in the array.
$ids = (array with all ids form the table)
for($i=50100;$i<=70100;$i++){
if(array_search($i, $ids) != -1){
$availableids[] = $i;
}
}
one way would be to create another table - fill it will all allowable numbers, then write a simple query to find the ones in the new table that are not in the original table.
Sort the accounts in the server, and find jumps in PHP while reading in the results. Any jump in the sorted sequence is "free for use", because they are ordered. You can sort with something like SELECT AccountNumber FROM Accounts SORT ASCENDING;.
To improve efficiency, store the free account numbers in another table, and use numbers from this second table until no more remain. This avoids making too many full reads (as in the first paragraph), which may be expensive. While you are at it, you may want to add a hook in the part of the code which deletes accounts, so they are immediately included in this second table, making the first step unnecessary.

Completely arbitrary sort order in MySQL with PHP

I have a table in MySQL that I'm accessing from PHP. For example, let's have a table named THINGS:
things.ID - int primary key
things.name - varchar
things.owner_ID - int for joining with another table
My select statement to get what I need might look like:
SELECT * FROM things WHERE owner_ID = 99;
Pretty straightforward. Now, I'd like users to be able to specify a completely arbitrary order for the items returned from this query. The list will be displayed, they can then click an "up" or "down" button next to a row and have it moved up or down the list, or possibly a drag-and-drop operation to move it to anywhere else. I'd like this order to be saved in the database (same or other table). The custom order would be unique for the set of rows for each owner_ID.
I've searched for ways to provide this ordering without luck. I've thought of a few ways to implement this, but help me fill in the final option:
Add an INT column and set it's value to whatever I need to get rows
returned in my order. This presents the problem of scanning
row-by-row to find the insertion point, and possibly needing to
update the preceding/following rows sort column.
Having a "next" and "previous" column, implementing a linked list.
Once I find my place, I'll just have to update max 2 rows to insert
the row. But this requires scanning for the location from row #1.
Some SQL/relational DB trick I'm unaware of...
I'm looking for an answer to #3 because it may be out there, who knows. Plus, I'd like to offload as much as I can on the database.
From what I've read you need a new table containing the ordering of each user, say it's called *user_orderings*.
This table should contain the user ID, the position of the thing and the ID of the thing. The (user_id, thing_id) should be the PK. This way you need to update this table every time but you can get the things for a user in the order he/she wants using ORDER BY on the user_orderings table and joining it with the things table. It should work.
The simplest expression of an ordered list is: 3,1,2,4. We can store this as a string in the parent table; so if our table is photos with the foreign key profile_id, we'd place our photo order in profiles.photo_order. We can then consider this field in our order by clause by utilizing the find_in_set() function. This requires either two queries or a join. I use two queries but the join is more interesting, so here it is:
select photos.photo_id, photos.caption
from photos
join profiles on profiles.profile_id = photos.profile_id
where photos.profile_id = 1
order by find_in_set(photos.photo_id, profiles.photo_order);
Note that you would probably not want to use find_in_set() in a where clause due to performance implications, but in an order by clause, there are few enough results to make this fast.

Search for column format

This is a bit of a difficult problem for me to word, and I may be going about it in the completely wrong way.
I'm storing a set of options in a database, where each option is its own column. The user can change the number of options, however, so I need a way of allowing PHP to always select all the options.
Let's say I have these columns: options_dialog_1, options_dialog_2, options_dialog_3, options_dialog_4
There could be a varying number of these dialog option columns, eg, another called options_dialog_5 could be added.
How do I select all the dialog option columns, based on their column name format?
I think you have a database design problem here; repeating columns like that always leads to trouble in the end. I think you need two tables, one for the user and one for the options defined something like this...
USERS
id
name
OPTIONS
id
user_id
option_dialogue_number
option_dialogue_value
That turns the columns into rows, which are rather easier to get at.
Brian's answer will really, really pay you off in longer period. But if you need something quick & ugly, you can check out the "metadata dictionary" (tables that store information about all other tables, columns etc). You could get list of columns from it with first query and use it to build the second one.
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='mytable' AND COLUMN_NAME LIKE 'options_dialog%'
Visit the manual on INFORMATION_SCHEMA for more goodies.
I am not sure I understand the problem. Are you looking for
SELECT * FROM options_table
Something like (faux SQL - wont work)
SELECT ( SELECT column_names where column_name LIKE 'options_dialog%' )
FROM options_table
sounds not feasible to me (though I am sure it's possible somehow). If you need this, either consider refactoring the database design or maybe use a bitmask to store the selected options in a single column.

Categories