I was reading through our code base at my company and I saw something that seemed like it could be done better.
$dbRow = $dbh->Execute("SELECT * FROM database.table LIMIT 1");
$tableColumnCount = $dbRow->_numOfFields;
Is this the only way to get a column count using ADODB? It just seems silly to have to execute a query so you can ask the question.
You can use the INFORMATION_SCHEMA.COLUMNS table:
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'your_table_name'
AND table_schema = 'your_database_name'
That said, you might want to run the FLUSH TABLES command prior to for the INFORMATION_SCHEMA.COLUMNS to reflect existing tables and columns because the data is cached.
Whichever way, you'll have to end up hitting the database unless your program can magically know the schema of the table. If LIMIT 0 is legal in MySQL then this would be slightly more efficient - as I expect would replacing LIMIT 1 with WHERE 1 = 0.
MetaColumns or MetaColumnNames should give you this information
Related
Currently I am trying to update the values in a column with a unique value. I use the following Query:
SET #a = 1; UPDATE table_name SET column_name = #a:=#a+1;
This query works when using it in phpMyAdmin. But I want to use this query in a php-script. My script is below, but when this is executed the column is not updated. I do not receive an error, so I do not have an indication of what is going wrong.
$sql = "SET #a = 1 UPDATE table_name SET column_name = #a:=#a+1";
$result = $link->query($sql);
Does anyone have a clue on how to solve this?
It sounds like you are trying to add a unique id to your table.
Are you are aware of auto_increment? If you give this to column_name it will automatically number the rows in increasing sequential order in the same manner you are trying to achieve with your current query.
https://www.w3schools.com/sql/sql_autoincrement.asp
I'm having to query from a Database that has more than 50 tables - all having the same structure (I know, Horrid Database design from a legacy project that's been in production for 5+ years!). To do this, I've queried the information_Schema like below:
SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.tables
WHERE TABLE_SCHEMA =
'projectdatabase'
AND
TABLE_NAME LIKE '%_usertable'
Which provides me the 50 or so tables that I need, in a result. Now, I will need to query columns from within each of those tables for example, PRODUCT_ID. In doing so, I've attempted:
SELECT
projectdatabase.userTable.PRODUCT_ID
FROM (
SELECT
TABLE_NAME as userTable
FROM
INFORMATION_SCHEMA.tables
WHERE TABLE_SCHEMA =
'projectdatabase'
AND
TABLE_NAME LIKE '%_usertable'
) AS userTables
Now this obviously doesn't work due to MySQL not treating the 'userTable' as Database table - but what I'm attempting to do, is query * FROM {tablename} where tablename was the information_schema query result.
I could attempt to split this up in PHP, although I'm eagerly wondering if this was possible to do within MySQL.
You have to use prepared statement:
SET #sql:=(SELECT GROUP_CONCAT(
CONCAT("SELECT PRODUCT_ID FROM ", TABLE_NAME) SEPARATOR " UNION ")
FROM INFORMATION_SCHEMA.tables
WHERE TABLE_SCHEMA = 'projectdatabase'
AND TABLE_NAME LIKE '%_usertable');
PREPARE stmt FROM #sql;
EXECUTE stmt;
EDIT: You can also set SET SESSION group_concat_max_len = 1000000;, but doing all in SQL is not a thing to do. Your table list is kind of a constant, and the query would be in a better place in your PHP code.
Adam deserves the bounty. The group_concat_max_len can be captured and restored if you like. And you can make it even larger. So I don't see a reliability issue. And I agree that you cannot have the tablename be a 'variable'.
The PHP equivalent would go something like:
Get the list of tables from
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.tables
WHERE TABLE_SCHEMA = 'projectdatabase'
AND TABLE_NAME LIKE '%_usertable';
Either build the UNION, Adam's suggestion, or run the 50 SELECT's, each based on one tablename from the above list. Then combine them however you want.
Recommend thinking through UNION DISTINCT versus UNION ALL.
I need to write some code that applies to only certain fields within our database. Specifically I'm looking for any field in all tables of a single database that are of type DECIMAL(12,5);
If it's of any help, all of our decimal fields are prefixed with dec_. I could gather all of the decimal fields from all tables, but there are tons of them that don't match my particular criteria, I need only the decimal values who's limit is 12,5.
I'd have no preference between doing this in pure SQL, or using PHP. We're currently using the CakePHP framework to manage our project, though I could just as easily do this without using the framework. This is a one time operation to gather the required data so I can continue forward with the audit.
Any help is greatly appreciated, thank you for taking the time to read this.
[EDIT] Got some great answers here, thanks everyone! I probably should have mentioned this in my initial post, but is there any way I can also get the table name associated with each field?
SELECT
TABLE_NAME,
COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'db-name' AND
DATA_TYPE = 'decimal' AND
NUMERIC_PRECISION = 12 AND
NUMERIC_SCALE = 5
You can try to use the following approach:
$pdo = new PDO(...);
$sql = "select column_name from
information_schema.columns
where table_schema='$your_db' and table_name='?' and data_type = 'decimal(12,5)'";
foreach($pdo->query("SHOW TABLES;") as $table) {
$prepared = $pdo->prepare($sql);
$prepared->execute(array($table));
print_R($prepared->fetchAll()) ;
}
Try this
SELECT table_name, column_name
FROM information_schema.columns where data_type = 'INT'
Im trying to get this query to work but i get this error:
Unknown column 'zips.city' in 'having clause'
`$query = "SELECT
zips.*
FROM
zips
HAVING
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
$result = mysql_query($query) or die (mysql_error());`
my zips table has a city column, so im not sure what the problem is, i know im accessing the database because i can run this query with no errors:
$zip1query = "SELECT
zips.*
FROM
zips
WHERE
zips.zip = '$zip'
";
any advice would be much appreciated! thanks!
The having clause doesn't mean the same thing as the where clause : when running a simple query, you should use where -- which is what you did in your second query, that works.
having is used when the condition has to be applied on the result of a group by clause.
Which means that, here, your query should be build this way :
$query = "SELECT zips.*
FROM zips
where zips.city LIKE '%$city%'
AND zips.stateabbr LIKE '%$state%'
LIMIT 1";
With that, if you still have an error about a non-existing or not-found column (at least for city and/or stateabbr), it'll be because that column doesn't exist in your table.
In this case, there is not much we can do : you'll have to check the structure of your table, to determine which columns it contains.
You can check that structure using a web-based tool like phpMyAdmin, or using an SQL instruction such as :
desc zips;
For reference, quoting MySQL's manual page for select :
The SQL standard requires that HAVING
must reference only columns in the
GROUP BY clause or columns used in
aggregate functions. ...
Do not use HAVING for items that
should be in the WHERE clause.
For example, do not write the
following:
SELECT col_name FROM tbl_name HAVING col_name > 0;
Write this instead:
SELECT col_name FROM tbl_name WHERE col_name > 0;
...
The HAVING clause can refer to
aggregate functions, which the WHERE
clause cannot
Try using WHERE instead of HAVING.
The proper way to do it is by using a WHERE clause.
$query = "SELECT
zips.*
FROM
zips
WHERE
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
HAVING is to be used when you are GROUPing, see here for an explanation
o jeez sorry guys i figured out the problem, apparently i put a space before city when i named the columns in my table. so i renamed the column and it works thanks anyway chaps! but using the where function instead of having must speed things up alot, thanks guys!
If I have this:
$results = mysql_query("SELECT * FROM table_name WHERE id=$id");
is there then any way to check how many rows which have a field-value of "Private" or "Company" ?
I need to show the user how many "Private" and "Company" records where found, without making another query. (There is a column called 'ad_type' which contains either "private" or "company")
I already know the mysql_num_rows for counting all rows!
EDIT:
There are 500thousand records! So maybe an iteration through the result is slow, what do you think?
Thanks for all help :)
The above answers are great and all, but the currently checked answer will work very inefficiently should you be dealing with a large amount of data
Example of the above answer (via Gal)
$results = mysql_query("SELECT *,(SELECT COUNT(*) FROM table_name WHERE column=$value) count FROM table_name WHERE id=$id");
It's good and all, and it returns what you need but the obvious design flaw is that making your SQL server return the results then re-return them and look at just the count is very inefficient for large amounts of data.
Simply do this:
$results = mysql_query("SELECT * FROM table_name WHERE column=$value");
$num_rows = mysql_num_rows($result);
It will yield the same results and be much more efficient in the long run, additionally for larger amounts of data.
You can do something like:
$results = mysql_query("SELECT *,(SELECT COUNT(*) FROM table_name WHERE column=$value) count FROM table_name WHERE id=$id");
in order to fetch the number with sql.
If you don't want to change your query you could do a
$results = mysql_query("SELECT * FROM table_name WHERE id=$id");
$count = mysql_num_rows($results);
steps to get a count():
use mysql_query() to get count,
use mysql_fetch_array() to get the only 1 row
get the only one column of the row, this is the count,
here is an example, which check whether the email is already used:
// check whether email used
$check_email_sql = "select count(*) from users where email='$email'";
$row = mysql_fetch_array(mysql_query($check_email_sql));
$email_count = $row[0];
Iterate through the result set of rows and count the number of occurences of Private and Company in ad_type, respectively?
You can do
SELECT COUNT(*) FROM table_name WHERE id=$id GROUP BY fieldvalue HAVING fieldvalue = "Private"
SELECT COUNT(*) FROM table_name WHERE id=$id GROUP BY fieldvalue HAVING fieldvalue = "Company"
but that would be another query. But if you process the data anyway, you could simply sum up the number of "Private" and "Company" rows after doing the query.
In the case you don't have to get all results, use this.
SELECT ad_type, COUNT(*)
FROM table_name
WHERE (id=$id)
GROUP BY ad_type
HAVING ((ad_type = 'Private') OR (ad_type = 'Company'))
If you still have to fetch all the records where id = $id, it won't work. But executing such a query (once) before fetching the real data should be more efficient than using a subquery.
I guess this query would do the job:
SELECT ad_type, count(*) FROM table_name WHERE id=$id GROUP BY ad_type;
I don't see any reason so far to use HAVING, since you probably want to show the user an overview of all the ad_type's found in DB (at least you didn't mention that there are other values for ad_type then the two given).
I also strongly suggest NOT to use sub-queries; always try to use just one.
If there's one thing that will slow your query down, it's a subquery (or subqueries).
Good luck!
Iterate through the results of the query and keep a count of how many of each show up in local variables.