I get error when i try to $_GET for VALUES - equivalence

this is the code ia m trying to make work but apparently this is not a viable lining of code:
$sql = "INSERT INTO users (name, pass)
VALUES ('$_GET['user'], '$_GET['pword']')";
error i get:
errorError: INSERT INTO users (name, pass) VALUES ('test', '123')
Unknown column 'pass' in 'field list'

First make sure you have passed column on your users table in the database
I'd rewrite your codes as follows
$username = $_GET['user'];
$password = md5( $_GET['pword']);
$sql = "INSERT INTO users (name, pass) VALUES ($username,$password)";

Related

CASE query in postgres does not return expected output

In my Postgres database, I am trying to execute the below query:
with
user_details as
(
SELECT username
FROM user_management WHERE username = 'admin'
)
select (case
when user_details.username is NOT NULL then 'user found'
else
'no user found' end) as username from user_details
The above query will return the username and works as expected. But if I pass the username that does not exist in the database, then I expect the CASE query to return 'no user found' but the query does not return anything at all.
But when I tried to execute the below query:
select (case
when (SELECT username
FROM user_management WHERE username = 'sadmin') is not null then 'user found'
else
'no user found' end) as username
It works as expected and returns the 'no user found'.
Why didn't I get the expected output when using the WITH query in the first case? Is there something with the WITH queries that I am missing?
When you're selecting the output from user_details , you're getting 0 rows , that is the reason you're not seeing any o/p in final result. And in the 2nd query , you're selecting the o/p from sub-query which is null then producing user not found. You might run into an error like this
ERROR: more than one row returned by a subquery used as an expression .
When there is more user having the same username. So your query should look like this
select (case
when exists(SELECT username
FROM user_management WHERE username = 'sadmin') then 'user found'
else
'no user found' end) as username
I assume that the column username is unique in the table user_management, so the CTE returns either 1 row when the username exists in the table or nothing if it does not exist.
Maybe you think that the CTE returns NULL in the case where the username does not exist in the table, but it is not.
So if the CTE returns 1 row (the username exists) then your code works fine, but if it returns nothing then your SELECT statement that selects from user_details will also return nothing, because there are no rows to select from.
Use aggregation so that you will get 1 row in the results even if the user does not exist:
SELECT COALESCE(MAX(username), 'no user found') username
FROM user_management
WHERE username = 'admin'
See the demo.

perl dbi prepare with variable table column name

I have used the following code many times before when inserting values into database tables using perl
my $SRV='xxx';
my $DB='dbname';
my $db = DBI->connect("dbi:Oracle:$SRV/$DB", "user", "pword" ) or die "impossible de se connecter à $SRV / $DB";
my $insert_T1 = "INSERT INTO tablename (ColA, ColB) VALUES ( ?, ?) " ;
my $insert_T1_sth = $db->prepare($insert_T1) ;
Later in the code I can then call the following to do the insertion
$insert_T1_sth->execute('val1','val2');
$insert_T1_sth->execute('val3','val4');
So basically when I use the prepare function above I can replace the entries I want to insert by question marks and then put the values of these question marks in the execute statements later on.
So to my question: Can I use question marks in place of column names in the prepare statement? I'm thinking no because when I try the following I get a runtime error on the line where the execute statement(s) are.
my $SRV='xxx';
my $DB='dbname';
my $db = DBI->connect("dbi:Oracle:$SRV/$DB", "user", "pword" ) or die "impossible de se connecter à $SRV / $DB";
$db->{AutoCommit} = 0 ;
my $insert_T1 = "INSERT INTO tablename (ColA, ?) VALUES ( ?, ?) " ;
my $insert_T1_sth = $db->prepare($insert_T1) ;
Then later, as before, use
$insert_T1_sth->execute('colname1','val1','val2');
$insert_T1_sth->execute('colname2','val3','val4');
You can't use dynamic column names with prepare like you are trying to do.
Your column names shouldn't be known to the user, and therefore don't really need to be part of the parameters, since they are not sensitive (and don't need to be protected against SQL injection). Preparing is still useful for performances though.
What I'd suggest is to do a prepare for each of you column name, and store those in a hash:
my #col_names = qw(colname1 colname2);
my %inserts;
for my $col (#col_names) {
$inserts{$col} = $db->prepare("INSERT INTO tablename (ColA, $col) VALUES (?, ?)");
}
...
$inserts{colname1}->execute('val1', 'val2');

sqlalchemy to create temporary table

I created a temporary table with sqlalchemy (with an underlying postgres database) that is going to be joined with a database table. However, in some cases when a value is empty '' then postgres throws the error:
failed to find conversion function from unknown to text
SqlAlchemy assembles everything to the following context
[SQL: 'WITH temp_table AS \n(SELECT %(param_1)s AS id, %(param_2)s AS email, %(param_3)s AS phone)\n SELECT campaigns_contact.id, campaigns_contact.email, campaigns_contact.phone \nFROM campaigns_contact JOIN temp_table ON temp_table.id = campaigns_contact.id AND temp_table.email = campaigns_contact.email AND temp_table.phone = campaigns_contact.phone'] [parameters: {'param_1': 83, 'param_2': '', 'param_3': '+1234567890'}]
I assemble the temporary table as follows
stmts = []
for row in import_data:
row_values = [literal(row[value]).label(value) for value in values]
stmts.append(select(row_values))
subquery = union_all(*stmts)
subquery = subquery.cte(name="temp_table")
The problem seems to be the part here
...%(param_2)s AS email...
which after replacing the param_2 results in
...'' AS email...
which will cause the error mentioned above.
One way to solve the issue is to perform a cast
...''::text AS email...
However, I don't know how to perform ::text cast with sqlalchemy!?

Fetching one single row from database using Perl

I am trying to run a simple database connection with Perl using postgreSQL
use DBI;
$database = "postgres";
$user = "postgres";
$password = "admin";
my $dbh = DBI->connect( "dbi:Pg:dbname=$database"
, $user
, $password
)
or die "Can't Connect to database: $DBI::errstr\n";
# get data from the URL string
my $firstname = "haroon";
my $lastname ="ash";
my $age = 24;
# insert the data into the database
my $query = "INSERT INTO people (firstname, lastname, age)
VALUES ('$firstname','$lastname', '$age')";
$dbh->do($query);
# get the ID of the inserted person
$query = "SELECT MAX(id) FROM people";
my $sth = $dbh->prepare($query);
my $rv =$sth->execute;
if($rv < 0){
print $DBI::errstr;
}
else {
my $row = $sth->fetchrow_hashref;
my $person_id = $row->{'max'};
print $firstname, $lastname
. "was successfully inserted at position "
. $person_id;
}
I am trying to print the person id which i had entered latest. But my $person_id = $row->{'max'} seems to give me the correct answer instead of my $person_id = $row->{'id'};. I am not understanding why is that.
You might want to set column alias for query,
$query = "SELECT MAX(id) AS id FROM people";
as postgres is putting his own alias for you, and that is max.
If all you want is last inserted id, you can
my $query = "INSERT INTO people (firstname, lastname, age)
VALUES (?,?,?)
returning id
";
and fetch query as you would do with select. (check pg docs)
You can use the RETURNING keyword to return the id associated with the row you just inserted:
my $query = '
INSERT INTO people (firstname, lastname, age)
VALUES ($1, $2, $3)
RETURNING id';
my $sth = $dbh->prepare($query);
$sth->execute($firstname, $lastname, $age);
my $rv = $sth->fetchrow_hashref();
printf "%s, %s was successfully inserted at position %d\n",
$firstname, $lastname, $rv->{id};
You did not enter a PERSON_ID in your insert statement.
Instead it seems the ID field was populated by the DB, an auto increment value during insert, it seems.
Without knowing the table definition (and potential insert trigger on the table) it is hard/impossible to give you a better answer.

String getting converted to number when inserting it in database through Perl's DBI $sth->execute() function

I'm using Perl's DBI and SQLite database (I have DBD::SQLite installed). I have the following code:
my $dbh = DBI->connect("dbi:SQLite:dbname=$db", "", "", { RaiseError => 1, AutoCommit => 1 });
...
my $q = "INSERT OR IGNORE INTO books (identica, book_title) VALUES (?, ?)";
my $sth = $dbh->prepare($q);
$sth->execute($book_info->{identica}, $book_info->{book_title});
The problem I have is when $book_info->{identica} begins with 0's they get dropped and I get a number inserted in the database.
For example, identica of 00123 will get converted to 123.
I know SQLite doesn't have types, so how do I make DBI to insert the identica as string rather than number?
I tried quoting it as "$book_info->{identica}" when passing to $sth->execute but that didn't help.
EDIT
Even if I insert value directly in query it doesn't work:
my $i = $book_info->{identica};
my $q = "INSERT OR IGNORE INTO books (identica, book_title) VALUES ('$i', ?)";
my $sth = $dbh->prepare($q);
$sth->execute($book_info->{book_title});
This still coverts 00123 to 123, and 0000000009 to 9...
EDIT
Holy sh*t, I did this on the command line, and I got this:
sqlite> INSERT INTO books (identica, book_title) VALUES ('0439023521', 'a');
sqlite> select * from books where id=28;
28|439023521|a|
It was dropped by SQLite!
Here is how the schema looks:
CREATE TABLE books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
identica STRING NOT NULL,
);
CREATE UNIQUE INDEX IDX_identica on books(identica);
CREATE INDEX IDX_book_title on books(book_title);
Any ideas what is going on?
SOLUTION
It's sqlite problem, see answer by in the comments by Jim. The STRING has to be TEXT in sqlite. Otherwise it treats it as number!
Changing schema to the following solved it:
CREATE TABLE books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
identica TEXT NOT NULL,
);
Use bind params
my $sth = $dbh->prepare($q);
$sth->bind_param(1, 00123, { TYPE => SQL_VARCHAR });
$sth->bind_param(2, $book_info->{book_title});
$sth->execute();
UPDATE:
Read about type affinity in SQLite. Because your column type is STRING (technically unsupported), it defaults to INTEGER affinity. You need to create your column as TEXT instead.
According to the docs, if the column type (affinity) is TEXT it should store it as a string; otherwise it will be a number.