Scenario:
I am exporting a table Named "Registration" from access database and writing into a file named "isl.txt" in php using pdo. Fields separated by "," and Records separated by "\\"(i know it should be "\n" for convenience but it cant take a new line in text file. Don't know why !! so i have chosen "\\")
Registration Table in Access:
Roll_Num,Course,Marks,Discipline,Session
0,CS-101,89,CS,Fall94
0,CS-102,70,CS,Fall94
0,CS-103,59,CS,Fall94
Code:
$fl = fopen('isl.txt', 'w');
$db = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=D:\Islamabad.mdb;Uid=;Pwd=;");
$results = $db->query("select * from `Registration`");
while ($row = $results->fetch()) {
foreach ($row as $value) {
$lastv = end($row);
if ($value != $lastv){
fwrite($fl, $value.",");
}
}
fwrite($fl, $value."\\");
}
fclose($fl);
Output:
0,0,CS-101,CS-101,89,89,CS,CS,Fall94\0,0,CS-102,CS-102,70,70,CS,CS,Fall94\0,0,CS-103,CS-103,59,59,CS,CS,Fall94
Problem:
As u see, every single value of record is repeating two times. Please Check whats wrong with my code!!
The repeating values are because you are not specifying a fetch_style in $results->fetch([fetch_style]). According to the manual - http://php.net/manual/en/pdostatement.fetch.php - when fetch_style is not specified, it defaults to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH).
PDO::FETCH_BOTH (default): returns an array indexed by both column
name and 0-indexed column number as returned in your result set
Try changing to -
while ($row = $results->fetch(PDO::FETCH_ASSOC)) {
OR
while ($row = $results->fetch(PDO::FETCH_NUM)) {
Related
I would get Joomla custom fields values from a PHP script. I include all necessary files and I can read checkbox values from "fields" table, the "fieldparams" column.
If I execute this code
$query = "select #__fields.fieldparams from #__fields where #__fields.id = 19";
$db->setQuery($query);
$result = $db->loadRowList();
foreach ($result as $value) {
echo gettype($value); // 01
echo $value[0]; // 02
$var = json_encode($value[0]);
echo gettype($var); // 03
}
the type of $value is "Array" (step 01), so if I access to $value[0] the result (step 02) is the global list (so I suppose this is an Array with 1 element)
{
"options":{
"options0":{"name":"type1","value":"1"},
"options1":{"name":"type2","value":"2"},
"options2":{"name":"type3","value":"3"},
"options3":{"name":"type4","value":"4"},
"options4":{"name":"type5","value":"5"}
}
}
but when I try to use json_encode the result (step 03) is a string.
In this way I can't access to keys and relative values.
What's wrong?
There are 2 issues here. 1. You're using ->loadRowList() which is a method designed to return an array of rows (i.e. multiple rows), not one as is implied by your where clause, and 2. Rather than using PHP's native functions, try using Joomla's JRegistry class instead.
To address these points:
1 Since you're only expecting 1 row to be returned (field with ID 19), replace your line:
$result = $db->loadRowList();
with
$result = $db->loadResult();
$result will contain the fieldparams column only.
2 Create an instance of the JRegistry class so we can access the key => value pairs:
// new registry
$registry = new JRegistry();
$registry->loadString($result); // load the string from the db
// if you need an array, use jregistry's toArray method
$arrayData = $registry->toArray();
Hope it helps,
Gez
How can I list names of tables in sql database and the table columns for the each table and then get a json encoding of the results in PHP?
Here is code to display tables:
$result = mysql_query("show tables"); // run the query and assign the result to $result
while($table = mysql_fetch_array($result)) {
// go through each row that was returned in $result
echo($table[0] . "<BR>"); // print the table that was returned on that row.
}
You could create an array/object and add the data to it. To get a json result just call json_encode on the array/object.
Here is what I would do:
// Create an object
$results = new stdClass();
// Get all tables
$result = mysql_query("show tables");
// Always check if the query returned anything to prevent possible errors
if(mysql_affected_rows() > 0) {
// Loop through each table
while($table = mysql_fetch_assoc($result)) {
// Get the columns in the table
$resultColumns = mysql_query("show columns from ".$table);
if(mysql_affected_rows() > 0) {
// Columns found. Create a new property in the object and assign the columns to it
$tableColumns = mysql_fetch_assoc($resultColumns);
$results[$table] = $tableColumns;
}
else {
// No columns found. Create a new property in the object and assign a blank array.
$results[$table] = [];
}
}
}
Now we can return that data as a json with json_encode($results).
http://php.net/manual/en/function.json-encode.php
As a side note, I would look to use mysqli, not mysql (as it is now depreciated). The syntax for it is basically exactly the same, but you need to pass the connection variable as the first parameter in most cases. So it would be useful to use create a database/connection class and call to those methods, instead of calling mysql or mysqli functions directly.
See here: https://www.w3schools.com/php/php_ref_mysqli.asp
And here (an example): https://www.johnmorrisonline.com/simple-php-class-prepared-statements-mysqli/
Note: This is pseudo code and not tested but should be okay. Let me know if you need any help with it.
I did a SELECT query on MySQL and get this as result.
The problem is how can I remove the 2nd duplicated results at for instance we use the 1st item in the list. "0":"1" is a duplicate for "id":"1" I would rather use "id" instead of "0" as the key later on the the app. How could I remove this to simplify the results. I do notice that the "0" means the 1st column as the successive columns does add up by 1.
Here's the $query I run.
SELECT id FROM clubsinformation WHERE :comparisonTime < updateTime
This is caused by most likely the fetching mode, you need to fetch it by associative indices only because right now you're including both associative and numeric index fetching:
No matter what DB API you got, MySQLi or PDO, just set it to associative.
So that it turn it doesn't include the numeric indices, only the column names as keys:
So this would roughly look like in code (from looking at your query placeholders, it seems PDO, so I'll draft a PDO example):
$data = array(); // container
$query = 'SELECT * FROM clubsinformation WHERE :comparisonTime < updateTime';
$select = $db->prepare($query);
$select->bindValue(':comparisonTime', $comparisonTime);
$select->execute();
while($row = $select->fetch(PDO::FETCH_ASSOC)) { // associative
$data[] = $row; // only includes column names
}
// then finally, encode
echo json_encode($data);
// OR SIMPLY
// $data = $select->fetchAll(PDO::FETCH_ASSOC); // associative
// echo json_encode($data);
That fetching is by way of PDO API. If you're using MySQLi you can still use the basic idea.
I am trying to get the full definition for constraints on a particular table in MSSQL via PHP's mssql.dll driver, and when I call next_result() on the returned resource from the original query "sp_helpconstraint ", I either get an empty result set, or it does not advance to the next table of data...
IS there a direct query to the sys. tables that I can make that will pull the equivalent information without the extra data set?
This same problem seems to exist with the SQL SERVER ddl supplied by MS as well.
Code is as follows:
$sql = '/* Getting '.$this->ExpectedTableVO->GetTableName().' Constraints */ sp_helpconstraint \''.$this->ExpectedTableVO->GetSchema().'.'.$this->ExpectedTableVO->GetTableName().'\'';
$r = $this->db->Query($sql);
$results['Constraints'] = array();
$r = $this->db->NextResult($r);
while ($row = $this->db->FetchObj($r))
{
$results['Constraints'][] = $row;
}
This results in an empty set, despite there being plenty of constraints on the table in question. Without NextResult, I get the Table with a single row and column "Object Name" with the table name...
Otherwise an empty set... WTF?!
I messed up...
Notice I overwrite $r with the nextresult() command... just calling that without overwriting it fixes this problem.
$sql = '/* Getting '.$this->ExpectedTableVO->GetTableName().' Constraints */ sp_helpconstraint \''.$this->ExpectedTableVO->GetSchema().'.'.$this->ExpectedTableVO->GetTableName().'\'';
$r = $this->db->Query($sql);
$results['Constraints'] = array();
$r = $this->db->NextResult($r);
//above line should be just "$this->db->NextResult($r);"
while ($row = $this->db->FetchObj($r))
{
$results['Constraints'][] = $row;
}
I'm using PHP ADOdb and I can get the result set:
$result = &$db->Execute($query);
How do I get the field names from that one row and loop through it?
(I'm using access database if that matters.)
It will depend on your fetch mode - if you setFetchMode to ADODB_FETCH_NUM (probably the default) each row contains a flat array of columns. If you setFetchMode to ADODB_FETCH_ASSOC you get an associative array where you can access each value by a key. The following is taken from ADODB documentation - http://phplens.com/lens/adodb/docs-adodb.htm#ex1
$db->SetFetchMode(ADODB_FETCH_NUM);
$rs1 = $db->Execute('select * from table');
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs2 = $db->Execute('select * from table');
print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')
To loop through a set of results:
$result = &$db->Execute($query);
foreach ($result as $row) {
print_r($row);
}
Small improvement to the solution posted by #thetaiko.
If you are ONLY needing the field names, append LIMIT 1 to the end of your select statement (as shown below). This will tell the server to send you a single row with column names, rather than sending you the entire table.
SELECT * FROM table LIMIT 1;
I'm working with a table that contains 9.1M records, so this minor change speeds up the query significantly!
This is a function I use to return a field array - I've stripped out some extra stuff that, for example, allows it to work with other DBs than MySQL.
function getFieldNames($strTable, $cn) {
$aRet = array();
# Get Field Names:
$lngCountFields = 0;
$strSQL = "SELECT * FROM $strTable LIMIT 1;";
$rs = $cn->Execute($strSQL)
or die("Error in query: \n$strSQL\n" . $cn->ErrorMsg());
if (!$rs->EOF) {
for ($i = 0; $i < $rs->FieldCount(); $i++) {
$fld = $rs->FetchField($i);
$aRet[$lngCountFields] = $fld->name;
$lngCountFields++;
}
}
$rs->Close();
$rs = null;
return $aRet;
}
Edit: just to point out that, as I say, I've stripped out some extra stuff, and the EOF check is therefore no longer necessary in the above, reduced version.
I initally tried to use MetaColumnNames, but it gave differing results in VisualPHPUnit and actual site, while running from the same server, so eventually
I ended up doing something like this:
$sql = "select column_name, column_key, column_default, data_type, table_name, table_schema from information_schema.columns";
$sql .= ' where table_name="'.$table.'" and table_schema="'.$database_name.'"';
$result = $conn->Execute($sql);
while($row = $result->fetchRow()) {
$out[] = strToUpper($row['column_name']);
}
I think it should work with mysql, mssql and postgres.
The benefit of doing it like this, is that you can get the column names, even if a query from a table returns an empty set.
If you need the Coloumn names even for empty tables or for joins about multiple tables use this:
$db->Execute("SELECT .......");
// FieldTypesArray - Reads ColoumnInfo from Result, even for Joins
$colInfo = $res->FieldTypesArray();
$colNames = array();
foreach($colInfo as $info) $colNames[] = $info->name;
The OP is asking for a list of fieldnames that would result of executing an sql statement stored in $query.
Using $result->fetchRow(), even with fetch mode set to associative, will return nothing if no records match the criteria set by $query. The $result->fields array would also be empty and would give no information for getting the fieldnames list.
Actually, we don't know what's inside the $query statement. Besides, setting limit to 1 may not compatible with all database drivers supported by PHP ADOdb.
Answer by Radon8472 is the right one, but the correct code could be:
$result = $db->Execute($query);
// FieldTypesArray - an array of ADOFieldObject Objects
// read from $result, even for empty sets or when
// using * as field list.
$colInfo = [];
if (is_subclass_of($result, 'ADORecordSet')){
foreach ($result->FieldTypesArray() as $info) {
$colInfo[] = $info->name;
}
}
I have the habit of checking the class name of $result, for as PHP ADOdb will return false if execution fails.