I have following table in MySQL
|Column1|Column2|Column3|
-------------------------
|Data1 |Data2 |Data3 |
|Data4 |Data5 |Data6 |
|Data7 |Data8 |Data9 |
|Data10 |Data11 |Data12 |
-------------------------
Now in this table, I am fetching column names as well all the 12 cells using PHP
here is the loop that I am working on.
for($i=0, $j=0; $i<$loopMax; $i++,$j++){//i run rows, j run columns
if($j>=$column_count){
$j=0;
}
$columns[$i][$j] = mysql_result($query_exec, $j, 'COLUMN_NAME');
$response[$i][$columns[$i][$j]] = #$result[$j];
}
print_r($response);
$maxLoop is the value of a number of columns multiplied by the number of rows. that way I get the total number of cells I need to fetch. I have to send this response in a json string so getting this cell values along with its respective column names is important because that's what is going to help the UI end recognize where to put which value.
there is no primary key to the table.
What I want to do is, fetch each of this cell value and the column name it belongs to and put it in an array. And send that array as jason string.
In case you have MySQL version 5.7.8 and above installed on your server, then you could use native JSON functions in your query.
SELECT JSON_OBJECT('Column1', `Column1`, 'Column2', `Column2`, 'Column3', `Column3`);
The result would be something like...
{ "Column1":"Data1", "Column2":"Data2", "Column3":"Data3" },
...
...
{ "Column1":"Data10", "Column2":"Data11", "Column3":"Data12" }
Try making naming rule for your column so you can get the column name like this:
$column_name = 'column' .'-' .$j
and this will work with the current column names without the hyphen like this:
$columns[$i][$j] = 'column' . $j
In other words you just append the value of $j to the word 'column'.
-Edit:
I think you can even calculate the column name in the front end of your application.
Related
I have a TXT file with no punctuation between them. I would like to shred this file by the table column widths in the database and save it.
Let me tell you this step by step…
I’m creating a table in the database with my tabloolustur.php page. The column numbers and column widths of the tables I create will not be the same.
There are no punctuation marks between the TXT file data. First, I want to split the TXT file rows by column width.
$result = $baglanti->prepare("SHOW COLUMNS FROM customers where Field NOT IN('id')");
$result->execute();
$colcount = $result->columnCount()-1;
$columLen = array();
foreach($result as $key => $col){
preg_match('/\d+/', $col['Type'], $len);
$len = (isset($len[0]))? $len[0] : '';
$fieldname = $col['Field'];
$columLen[$fieldname] = $len;
}
For this, I get the number of columns and column widths with the code.
Then, I separate the data with commas with the following function.
function txtBol($metin, $genislik){
$parcala=array();
foreach ($genislik as $sutunadi => $lenght)
{
$parcala[$sutunadi] = substr($metin, 0, $lenght);
$metin = substr($metin, $lenght);
}
return $parcala;
}
I also get column names with the following code. (ps: to use in a query)
$KolAdi = $baglanti->query("SHOW COLUMNS FROM customers where Field NOT IN('id')");
$KolAdi->execute();
$colonAdi= $KolAdi->fetchAll(PDO::FETCH_COLUMN);
$colonAdi=implode(',', $colonAdi);
It prints the data i split correctly when printing it to the screen. So far, so good. But I can’t create the right query with PDO. How should I create the query? (ps: Table column names and column widths are not the same. There will be different numbers and width columns for each table)
I would appreciate it if you could help. I proceeded by implementing some solutions from your site.
Table:
id
name
cev1
cev2
cev3
1
MARTIN EDEN
AAAAAA
BBBBB
CCCC
txt:
MARTIN EDEN........AAAAAABBBBBDDDD
Assuming a valid PDO connection in $PDO, you can do the whole job like this.
It reads the column data once and uses that to create a query to prepare and a regular expression to extract the data.
$table = 'customer';
$txtFile = 'cust.txt';
// No need to prepare this since there's no untrusted data here.
$result = $pdo->query("show columns from `$table` where Field <> 'id'");
// Get column names and widths in arrays
while($columns = $result->fetch(PDO::FETCH_ASSOC)) {
$colNames[] = $columns['Field'];
preg_match('/\d+/', $columns['Type'], $len);
$colLengths[] = $len[0]??'';
}
// Create regex to extract data from lines:
// Looks like this: /(.{20})(.{10})(.{5})/
$regex = '/(.{'.implode('})(.{',$colLengths).'})/u';
// Create skeleton query with table name and field names and placeholders
// Looks like this: INSERT customer (name,addr1,postcode) VALUES (?,?,?)
$query = "INSERT $table (`".implode('`,`', $colNames).'`) VALUES ('.str_repeat('?,', count($colNames)-1).'?)';
// Read text file
if ($fileData = file($txtFile)) {
// Prepare the query only once
$stmt = $pdo->prepare($query);
foreach ($fileData as $row) {
// Get the data using the regex from above
preg_match($regex, $row, $rowData);
// Remove the first row of the regex matches - see PHP manual for why
array_shift($rowData);
// Now execute the prepared query using the data extracted by the regex.
$stmt->execute($rowData);
}
}
Note that this codes assumes that the table consists of a series of contiguous columns from which it can extract column widths, and no other columns except id, which it ignores. If your actual table structure is different you'll need to modify the SHOW COLUMNS query to omit those columns, or modify the code that extracts the column data to extract only the relevant columns.
{Edit]
Updated the code to include /u UTF-8 modifier on the regex, and to wrap the column names in the INSERT query in back ticks.
you can create a table like this and you don't need to check a number of fields by rows
let me know if this useful
CREATE TABLE new_table (
id INT NOT NULL AUTO_INCREMENT,
row_id INT NULL DEFAULT 0,
row_field_name VARCHAR(50) NULL DEFAULT NULL COMMENT 'Index of ',
row_value VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (id));
I have a table which holds truck info . I have another table which holds driver info (name and truck id there two of them in each trip) . I make a daily report from the first table regarding it's current status and I want to have a cell which holds the two current drivers. When I do join on the tables I get two rows from each truck and the only difference is the name of the driver.
Is there a way to produce a single row (either PHP or SQL query) ?
to get an idea my current result is this :
Truck:DRIVER1:Date:Destination:Cargo:Remarks
Truck:DRIVER2:Date:Destination:Cargo:Remarks
And I want to get something like this :
Truck:DRIVER1 DRIVER2:Date:Destination:Cargo:Remarks
is that even possible ? I'm fairly new to this
Say for example you have stored first fetched string in $str1 and second in the second variable $str2.
You can now just use ltrim() and rtrim() functions as
<?php
$str1 = 'Truck:DRIVER1:Date:Destination:Cargo:Remarks';
$str2 = 'Truck:DRIVER2:Date:Destination:Cargo:Remarks';
$result = ltrim($str2,'Truck:');
$result = rtrim($result,':Date:Destination:Cargo:Remarks');
?>
After this you get the value of $result as DRIVER2
And then you can just concatenate the result into string one as
$str1 = 'Truck:DRIVER1 '.$result.':Date:Destination:Cargo:Remarks';
And when you echo the $str you will get the desired output
Output
Truck:DRIVER1 DRIVER2:Date:Destination:Cargo:Remarks
this is my current code:
for ($i=($loop1-($count-1)); $i <=$loop1 ; $i++)
{
${'track_' . $i}=$_POST['marks'.$i];
$in="insert into s_101483011(q".($i-20).") value('".${'track_' . $i}."')";
$inq=mysqli_query($db,$in);
}
First of all, please make sure that you set default values for the columns in case of not mentioning them in the insert query.
For the dynamic part, you can create a map object and generate sql sentence by using that map object that is expected to contain column and corresponding value.
I have a table which stores the ID of support cases using the primary key (column name = caseid).
I have now got to about 100,000 caseid and the number is just too big. I wish to somehow start from a lower number such as 1000.
How do I achieve something like this by not having to delete/archive existing records and not having to change the unique caseid's to another column (keep it as the primary key column)
To reset Primary Key, you can follow below steps:
Create temporary table with structure same as main table. Let's say table name is tbl_cases
CREATE TABLE tbl_cases_tmp LIKE tbl_cases;
ALTER TABLE tbl_cases_tmp ADD old_caseid int NOT NULL DEFAULT '0';
DUMP all data from tbl_cases to tbl_cases_tmp. caseid will be stored in old_caseid column.
INSERT INTO tbl_cases_tmp (name, summary, old_caseid)
SELECT name, summary, caseid FROM tbl_cases;
For any other tables having references to tbl_cases. Let's say tbl_reference
UPDATE tbl_reference tr
JOIN tbl_cases_tmp tc
ON tr.caseid = tc.old_caseid
SET tr.caseid = tc.caseid;
Before using Steps 4 and 5, ensure your tables tbl_cases_tmp and all references are properly updated.
Drop tbl_cases
DROP table tbl_cases;
Rename tbl_cases_tmp to tbl_cases
RENAME TABLE tbl_cases_tmp TO tbl_cases;
What about find lowest id and subtract its Value from all ids?
Then you'll be able to re-set the id to a lower number
Edit:
This suppose that there are unused ids and no recods related to them
In case your problem is with conveying the caseid e.g. from the customer via phone to the help desk you might consider leaving the actual case id as-is but change the alphabet/set of digits when showing it.
E.g. switch from decimal to hexadecimal and you've increased the range of values that can be displayed as four digits/characters from 9999 to 65535 (hex:ffff).
Now consider a different set of digits like 3479ACEFHJKLMNPRTUVWXY* and the range of numbers that can be displayed using only four digits/characters increases quite a lot.
<?php
echo getCode(234255), "\r\n"; // up until "here": four digits
echo getCode(234256), "\r\n"; // ok, now it's five
echo getCode(5100000), "\r\n"; // but stays five until > 5 millions
function toBase(/* positiv integer*/ $n, array $alphabet) {
$retval = '';
do {
$retval = $alphabet[ $n%count($alphabet) ] . $retval;
$n = intval( $n / count($alphabet) );
}
while( ($n=intval($n)) > 0);
return $retval;
}
function getCode(/*int*/ $caseid) {
static $alphabet = ['3','4','7','9','A','C','E','F','H','J','K','L','M','N','P','R','T','U','V','W','X','Y'];
return toBase($caseid, $alphabet);
}
prints
YYYY
43333
YTYAA
*) an alphabet containing only unambiguous characters.
I am looking to take the ID that auto increments already from the latest row in a table and increment it by one and append it on to a returned result from that same table. So if the row id is 5 and the tabledata result is product5, I need it changed to product6 in the php result. So when the data is resubmitted it is in-line with the new row ID.
EDIT:
I need it displayed and incremented before the sql insert because it's also emailed on data submit for ordering. The database insert is just to retain the order record.
Current code display results:
$conn=mysql_connect(" "," "," ");
mysql_select_db("database",$conn);
$sql="SELECT * FROM table WHERE ID=(SELECT max(ID) FROM table)";
$rs=mysql_query($sql,$conn) or die(mysql_error());
$result=mysql_fetch_array($rs);
echo '<table>
<tr>
<td>Data: '.$result["tabledata"].'</td>
</tr>
</table>';
?>
What if you modify the query to select value after incrementing it. i.e.
SELECT ID+1 AS ID, /*all other fields of the table */ FROM table WHERE ID=(SELECT max(ID) FROM table)
So if I understand, you have two fields, not one:
id tabledata
1 PO-01
5 product5
is a Purchase order field so it stays in line with the previous just one number different (Example PO-01 to PO-02)
First thing that comes to mind is not to write that number in two places anyway. You could have
id tabledata
1 PO-%02d
5 product%d
and then wherever you had the row data, you could use
sprintf($row['tabledata'], $row['id'])
to get the "human readable" version of tabledata. Then to get the "next" ID you could just do
sprintf($row['tabledata'], $row['id'] + 1)
Otherwise, you need to extract the number from the text field. This requires that you know in advance its format (e.g. is it %d or %02d or...?).
If you know it is just the number, with variable length, as in your first example (product5 to product6), you do
$table['tabledata'] = preg_replace('#\\d+$#', $table['id'] + 1);
The above will replace the last sequence of numeric digits (here, 5; it could be 1701 for example) with 6. Or you can capture the number with preg_match and much the same expression, only in parentheses, increment it, and store it back.
If it is a fixed-length sequence of numbers as in your second example (PO-01 to PO-02), you just use substr:
$size = 2; // Two-digit number
$num = substr($table['tabledata'], -$size);
$prd = substr($table['tabledata'], 0, -$size);
$table['tabledata'] = $prd . sprintf("%0{$size}d", $num + 1);
An even more complicated solution would be to merge the two versions into a "decoding" function that would count leading zeroes and digit lengths and use this to determine the format being used. This however would have problems in some cases (e.g. maybe the next number out from AB-99 is not AB-100 but AC-00 or AC-01), so all in all I think this is best left to someone with the knowledge of the specific domain.