Today I thought I would write a small bash script to create DB tables on a SQL database. What I thought would be quick turned out differently. Anyway I'm at a mental block and need advice. What I was want to do in the end is have the user enter the amount of columns in the table, then specify the column label and data type for the amount they entered to begin with. Then I'll take the array elements to assemble my SQL server command. It seemed rather obvious to me at first but not so much anymore. Any help is appreciated!
I was going to do something like...
#!/bin/bash
echo "Enter database name: "
read dbname
echo "Enter table name: "
read tablename
echo "Enter column count: "
read columns
echo "Enter database username: "
read dbuser
echo "Enter database user password: "
read dbpw
for i in ${columns[#]} do
echo "Column "$i" Name: "
read array_cname[$i]
echo "Column "$i" Data Type: "
read array_ctype[$i]
done
table="USE $dbname CREATE TABLE $tablename(array_cname[] array_ctype[] etc etc etc)"
mysql -u$dbuser -p$dbpw -e "$table"
The above is obviously a broken script, I just whipped it up after having cannibalized what I originally had going.
I'm just going to look at the part that you're struggling with - looping over the columns - and you should be able to take these lessons back to your script.
This is what I wrote, omitting the easy bits you've done, and setting columns to 2, to save typing whilst I tested.
#!/bin/bash
columns=2
declare -a cols
for ((i=1; i<=$columns; i++))
do
read -p "Column $i Name: " n
read -p "Column $i Data Type: " t
cols[$i]="$n $t"
done
echo "CREATE TABLE t (${cols[*]} etc etc etc)"
Explanation
I use declare to ensure that our array variable is of the correct type. Bash will infer it's an array when we first assign to an element, but I like to be clear.
To enumerate the integers from 1 to $columns, I use a Bash for loop.
You were missing the semicolon or newline between for and do.
Instead of trying to read directly into array elements, I read into two temporaries: n for name and t for type. I also use -p to make read emit the prompt for us.
I don't use two separate arrays for name and type, because Bash doesn't provide a simple way to interleave the values. Instead, I put name and type into a single array element. I could put them into separate elements if needed, with cols+=("$n" "$t").
To expand all elements of the array in a substitution, I use ${cols[*]}.
I haven't done any validation on the input; I'm assuming this script is a convenience for your own use, rather than a robust tool to share.
Test result
$ ./36337995.sh
Column 1 Name: a
Column 1 Data Type: int
Column 2 Name: b
Column 2 Data Type: int
CREATE TABLE t (a int b int etc etc etc)
Related
I want to change the column name with a descriptive name, like in my table I have a field name "job_title",
I want to replace this heading with "what is your job title", and job_description with "Describe your job description"
For accomplishing this task I can use Aliasing but I want to change the column names dynamically instead of hard code.
I have described these questions in the comments section of the individual field of the table and I am trying to fetch these comments from the database and display comments of the field as the column heading but couldn't accomplish it.
This is my PHP code:
$sql_getcolumns="select * interview_col_comments where table_name ='interview'";
$result = $mysqli->query($sql_getcolumns);
echo "<table>";
echo "<tr>";
while($row = mysqli_fetch_array($result))
{
echo "<th>".$row[0]."</th>";
}
echo "";
I also tried to find a way in the PhpMyAdmin interface if I labeled column names and retrieve labels using a query in PHP
but didn't find this option in the SQL interface.
Is there another Approach using PHP, or SQL Which I can use to give columns of the table descriptive names?
One approach can be make an array in php like below.
<?php $comment=[
'job_title' => "what is your job title",'job_description'=>"Describe your job description"];
echo "<th>".$comment[$row[0]]."</th>";
?>'
Another approach can be make a another table with column description in mysql and replace on run time.
id|column_id|description
1|job_title|"what is your job title"
2|job_description|"Describe your job description"
What you are looking for is called "localization".
There are many ways to do that.
I usually ALSO prefer to keep this information tightly wired to the database I'm working with, so what I did is:
I used the Database Column's Comment field to provide meta-information.
For example, a columns comment can look like this:
#required #de=Vertragsnummer #en=Contract_Number #search
Now, using the following query, I can retrieve the comments, and build a ColumnMetadataObject out of the information using some regex / string operations.
SELECT
c.`TABLE_NAME`,
c.`COLUMN_NAME`,
c.`COLUMN_COMMENT`,
t.`TABLE_COMMENT`
FROM
information_schema.columns c left join
information_schema.TABLES t ON
c.TABLE_NAME = t.TABLE_NAME and
c.TABLE_SCHEMA = t.TABLE_SCHEMA
where
c.`table_schema` = 'MyDatabase'
After parsing the information and providing the required Meta-Data-Objects, My header output just looks like this:
<?=$db->getColumnMetdata('contractNumber')->getHeader($_SESSION["user_language"]));?>
Code in between can vary in complexity. My ColumnMetadata also contains other information like required, searchable, length, possible foreign keys, and much more. That part would be up to you - just for localize headers, an associative Array would work as well. something like :
["de"] => {
"table1.contractNumber" => "Vertragsnummer"
"table1.Id" => "Id"
}
Answer found (syntax): The column name of my string had to be encased in backticks " ` " as they contained spaces. Note that this means that the majority of this post has no relevance to the issue. The code has been corrected in case someone wants to do something similar.
So, I am doing a foreach loop to assign a value (1/0) to non-static columns in my database (it needs to support addition/deletion/editing of columns). I am using $connectionvar->query($queryvar); to do my queries which worked fine up until now when I'm trying to use a custom built string as $queryvar in order to change the column name to a variable within the loop. I've been outputting this string through echo and it looks exactly like my functional queries but somehow doesn't run. I've attempted to use eval() to solve this but to no avail (I feel safe using eval() as the user input is radio buttons).
Here's the loop as well as my thought processes behind the code. If something seems incoherent or just plain stupid, refer to my username.
foreach($rdb as $x) { //$rdb is a variable retrieved from $_POST earlier in the code.
$pieces = explode("qqqppp", $x); //Splits the string in two (column name and value) (this is a workaround to radio buttons only sending 1 value)
$qualname = $pieces[0]; //Column name from exploded string
$qualbool = $pieces[1]; //desired row value from exploded string
$sql = 'UPDATE users SET '; //building the query string
$sql .= '`$qualname`';
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\''; //$profilename is retrieved earlier to keep track of the profile I am editing.
eval("\$sql = \"$sql\";"); //This fills out the variables in the above string.
$conn->query($sql); //Runs the query (works)
echo ' '.$sql.' <br>'; //echoes the query strings on my page, they have the exact same output format as my regular queries have.
}
}}
Here's an example of what the echo of the string looks like:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
For comparison, echoing a similar (working) query variable outside of this loop (for static columns) looks like this:
UPDATE users SET profiletext='qqq' WHERE username='Admin2'
As you can see the string format is definitely as planned, yet somehow doesn't execute. What am I doing wrong?
PS. Yes I did research this to death before posting it, as I have hundreds of other issues since I started web developing a month ago. Somehow this one has left me stumped though, perhaps due to it being a god awful hack that nobody would even consider in the first place.
You need to use backticks when referring to column names which have spaces in them. So your first query from the loop is outputting as this:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
But it should be this:
UPDATE users SET `Example Qualification 3`='1' WHERE username='Admin2'
Change your PHP code to this:
$sql = 'UPDATE users SET `'; // I added an opening backtick around the column name
$sql .= '$qualname`'; // I added a closing backtick around the column name
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\'';
Example Qualification 3 : Is that the name of your Mysql Column name ?
You shouldnt use spaces nor upper / lower case in your columnname.
Prefere : example_qualification_3
EDIT :
To get column name and Comment
SHOW FULL COLUMNS FROM users
I'm working with a table in which information is stored in a table in JSON format. The JSON value field looks like:
select * from k2_extra_fields where id = 2 and published = 1;
id | value
2,[{"name":"Apples","value":1,"target":null,"alias":"","required":0,"showNull":1},{"name":"Pears","value":2,"target":null,"alias":"","required":0,"showNull":1},{"name":"Mangos","value":3,"target":null,"alias":"","required":0,"showNull":1},{"name":"Guava","value":4,"target":null,"alias":"Fruit","required":0,"showNull":1},{"name":"Pineapple","value":5,"target":null,"alias":"Fruit","required":0,"showNull":1}]
Or values in a simple line by line view (minus the ID):
[
{"name":"Apples","value":1,"target":null,"alias":"","required":0,"showNull":1},
{"name":"Pears","value":2,"target":null,"alias":"","required":0,"showNull":1},
{"name":"Mangos","value":3,"target":null,"alias":"","required":0,"showNull":1},
{"name":"Guava","value":4,"target":null,"alias":"Fruit","required":0,"showNull":1},
{"name":"Pineapple","value":5,"target":null,"alias":"Fruit","required":0,"showNull":1}
]
The query that leads me here returns the value of 3. 3 = Mangos. How do I take the '3' value and match it up with the stored names/values so that I end up with the output, Mangos?
It should be possible with build in mysql functionality, but very hard and 'not clever' idea to do. If you really need to compute this problem within mysql, you would need to actually add new funtionality to your mysql. Look up on UDF plugins: http://dev.mysql.com/doc/refman/5.1/en/udf-compiling.html
usersim interested how do i select a text field form my mysql database, i have a table named users with a text field called "profile_fields" where addition user info is stored. How do i access it in php and make delete it? I want to delete unvalidate people.
PHP code
<?php
//Working connection made before assigned as $connection
$time = time();
$query_unactive_users = "DELETE FROM needed WHERE profile_fields['valid_until'] < $time"; //deletes user if the current time value is higher then the expiring date to validate
mysqli_query($connection , $query_unactive_users);
mysqli_close($connection);
?>
In phpmyadmin the field shows (choosen from a random user row):
a:1:{s:11:"valid_until";i:1370695666;}
Is " ... WHERE profile_fields['valid_until'] ..." the correct way?
Anyway, here's a very fragile solution using your knowledge of the string structure and a bit of SUBSTRING madness:
DELETE FROM needed WHERE SUBSTRING(
profile_fields,
LOCATE('"valid_until";i:', profile_fields) + 16,
LOCATE(';}', profile_fields) - LOCATE('"valid_until";i:', profile_fields) - 16
) < UNIX_TIMESTAMP();
But notice that if you add another "virtual field" after 'valid_until', that will break...
You can't do it in a SQL command in a simple and clean way. However, the string 'a:1:{s:11:"valid_until";i:1370695666;}' is simply a serialized PHP array.
Do this test:
print_r(unserialize('a:1:{s:11:"valid_until";i:1370695666;}'));
The output will be:
Array ( [valid_until] => 1370695666 )
So, if you do the following, you can retrieve your valid_until value:
$arrayProfileData = unserialize('a:1:{s:11:"valid_until";i:1370695666;}');
$validUntil = arrayProfileData['valid_until'];
So, a solution would be to select ALL items in the table, do a foreach loop, unserialize each "profile_fields" field as above, check the timestamp, and store the primary key of each registry to be deleted, in a separate array. At the end of the loop, do a single DELETE operation on all primary keys you stored in the loop. To do that, use implode(',', $arrayPKs).
It's not a very direct route, and depending on the number of registers, it may not be slow, but it's reliable.
Consider rixo's comment: if you can, put the "valid_until" in a separate column. Serializing data can be good for storage of non-regular data, but never use it to store data which you may need to apply SQL filters later.
I have a form on a page containing:
a text entry box named teachername
a text entry box named day (in the format YYYY-MM-DD)
a selection box named "resource" with the options [Library 1 or Library 2]
a selection box with the values [1,2,3 and 4] named block.
My mysql database has the fields:
- Teacher
Library1block1
Library1block2
Library1block3
etc.
The data from the html page is passed onto a php page meant to match the resource and block with the correct mysql field, and update the field so that the data from the text entry box "teachername" is inserted into it.
if ($_POST['resource']="Library 1" and $_POST['block']="1")
{mysql_query(
"UPDATE Resources
SET Teacher='yes', Library1block1='$_POST[teachername]'
WHERE Date='$_POST[day]'");}
if ($_POST['resource']="Library 1" and $_POST['block']="2")
{mysql_query(
"UPDATE Resources
SET Teacher='yes', Library1block2='$_POST[teachername]'
WHERE Date='$_POST[day]'");}
Expected:
- Enter "Mr. Smith" into teachername text entry field, select "Library 1" and "1" within the selection menu, and enter "2012-03-16" in the text entry field named day
Data is stored and passed along to the php script
an if statement updates the database record containing the field matched by the "resource"
field and "block" field (library1b1, library1b2, etc) for the date entered in the day text field
the field is updated, and the subsequent if statements check to match up the entered data with the correct mysql field
Result:
All fields (not just the specified field) are updated according to the first if statement.
EX: Entering in "Mr. Smith" for teachername, selecting "Library 1", selecting "1" for the block, and entering "2012-03-16" for the date does not update only the Library1block1 field, but it also updates the Library1block2 and library2block1 fields.
The mysql statement, when entered directly into a mysql terminal, updates the singular field correctly, but the usage of this php code results in multiple updated rows.
Help please?
You are making a common mistake of using the assignment operator (=) rather than the equality operator (==). On lines that look like this:
if($_POST['resource']="Library 1")
Change them to use the comparison operator:
if($_POST['resource'] == "Library 1")
The folks who have given answers have done a good job, but I would like to add one little trick that I like to use sometimes (depending on the language, etc.)
Usually you will write an if statement as something like
if ( $var == 1 ) { do_stuff( $var ) }; //or whatever
This following simple little trick has made this potential mistake almost impossible for me to make (esp. with php).
Just switch the two around.
So instead of the usual:
if ( $var == 1 ) { do_stuff( $var ) }; //or whatever
Try this instead whenever you can:
if ( 1 == $var ) { do_stuff( $var ) }; //or whatever
I'm pretty sure php 5.2+ hasn't changed to the point that it no longer works, but even if you make the mortal mistake of using a single equals sign it should still work because you can't assign a value to a constant (numbers are constant values, right?).
I believe this relies on php's behavior of always processing code from left to right:
if ( 1 = $var ) { do_stuff( $var ) }; //or whatever
And you're golden! Since I started doing this over 5 years ago I have never run into this problem again. 1 is always 1, no matter what you do. This is a good way of thinking through your conditionals, loops, etc. in php.
The beauty of this is in its mind smacking simplicity. "$var" can be lots of things, but the number 1 is always the number 1. I'm sure this doesn't work for all languages, but for php, it's one I use a lot, and it's apparently a good habit anyway to structure your code this way.
You should use two equal signs like this in you if statements to compare values:
$_POST['resource']=="Library 1"
This will check if $_POST['resource'] equals (==) Library 1
A single equal sign assigns Library 1 to $_POST['resource']
You may check Comparison Operators on php.net for more information:
http://php.net/manual/en/language.operators.comparison.php
Edit:
You should also use mysql_real_escape_string() for user input value such as $_POST:
if ($_POST['resource'] == "Library 1" and $_POST['block'] == "2")
{
mysql_query(
"UPDATE Resources
SET
Teacher='yes',
Library1block1='".mysql_real_escape_string($_POST['teachername'])."'
WHERE
Date='".mysql_real_escape_string($_POST['day'])."'"
);
}