Cannot simply use PostgreSQL table name ("relation does not exist") - php

I'm trying to run the following PHP script to do a simple database query:
$db_host = "localhost";
$db_name = "showfinder";
$username = "user";
$password = "password";
$dbconn = pg_connect("host=$db_host dbname=$db_name user=$username password=$password")
or die('Could not connect: ' . pg_last_error());
$query = 'SELECT * FROM sf_bands LIMIT 10';
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
This produces the following error:
Query failed: ERROR: relation "sf_bands" does not exist
In all the examples I can find where someone gets an error stating the relation does not exist, it's because they use uppercase letters in their table name. My table name does not have uppercase letters. Is there a way to query my table without including the database name, i.e. showfinder.sf_bands?

From what I've read, this error means that you're not referencing the table name correctly. One common reason is that the table is defined with a mixed-case spelling, and you're trying to query it with all lower-case.
In other words, the following fails:
CREATE TABLE "SF_Bands" ( ... );
SELECT * FROM sf_bands; -- ERROR!
Use double-quotes to delimit identifiers so you can use the specific mixed-case spelling as the table is defined.
SELECT * FROM "SF_Bands";
Re your comment, you can add a schema to the "search_path" so that when you reference a table name without qualifying its schema, the query will match that table name by checked each schema in order. Just like PATH in the shell or include_path in PHP, etc. You can check your current schema search path:
SHOW search_path
"$user",public
You can change your schema search path:
SET search_path TO showfinder,public;
See also http://www.postgresql.org/docs/8.3/static/ddl-schemas.html

I had problems with this and this is the story (sad but true) :
If your table name is all lower case like : accounts
you can use: select * from AcCounTs and it will work fine
If your table name is all lower case like : accounts
The following will fail:
select * from "AcCounTs"
If your table name is mixed case like : Accounts
The following will fail:
select * from accounts
If your table name is mixed case like : Accounts
The following will work OK:
select * from "Accounts"
I dont like remembering useless stuff like this but you have to ;)

Postgres process query different from other RDMS. Put schema name in double quote before your table name like this, "SCHEMA_NAME"."SF_Bands"

Put the dbname parameter in your connection string. It works for me while everything else failed.
Also when doing the select, specify the your_schema.your_table like this:
select * from my_schema.your_table

If a table name contains underscores or upper case, you need to surround it in double-quotes.
SELECT * from "Table_Name";

I had a similar problem on OSX but tried to play around with double and single quotes. For your case, you could try something like this
$query = 'SELECT * FROM "sf_bands"'; // NOTE: double quotes on "sf_Bands"

This is realy helpfull
SET search_path TO schema,public;
I digged this issues more, and found out about how to set this "search_path" by defoult for a new user in current database.
Open DataBase Properties then open Sheet "Variables"
and simply add this variable for your user with actual value.
So now your user will get this schema_name by defoult and you could use tableName without schemaName.

You must write schema name and table name in qutotation mark. As below:
select * from "schemaName"."tableName";

I had the same issue as above and I am using PostgreSQL 10.5.
I tried everything as above but nothing seems to be working.
Then I closed the pgadmin and opened a session for the PSQL terminal.
Logged into the PSQL and connected to the database and schema respectively :
\c <DATABASE_NAME>;
set search_path to <SCHEMA_NAME>;
Then, restarted the pgadmin console and then I was able to work without issue in the query-tool of the pagadmin.

For me the problem was, that I had used a query to that particular table while Django was initialized. Of course it will then throw an error, because those tables did not exist. In my case, it was a get_or_create method within a admin.py file, that was executed whenever the software ran any kind of operation (in this case the migration). Hope that helps someone.

In addition to Bill Karwin's answer =>
Yes, you should surround the table name with double quotes. However, be aware that most probably php will not allow you to just write simply:
$query = "SELECT * FROM "SF_Bands"";
Instead, you should use single quotes while surrounding the query as sav said.
$query = 'SELECT * FROM "SF_Bands"';

You have to add the schema first e.g.
SELECT * FROM place.user_place;
If you don't want to add that in all queries then try this:
SET search_path TO place;
Now it will works:
SELECT * FROM user_place;

Easiest workaround is Just change the table name and all column names to lowercase and your issue will be resolved.
For example:
Change Table_Name to table_name and
Change ColumnName to columnname

It might be silly for a few, but in my case - once I created the table I could able to query the table on the same session, but if I relogin with new session table does not exits.
Then I used commit just after creating the table and now I could able to find and query the table in the new session as well. Like this:
select * from my_schema.my_tbl;
Hope this would help a few.

Make sure that Table name doesn't contain any trailing whitespaces

Try this: SCHEMA_NAME.TABLE_NAME

I'd suggest checking if you run the migrations or if the table exists in the database.

I tried every good answer ( upvote > 10) but not works.
I met this problem in pgAdmin4.
so my solution is quite simple:
find the target table / scheme.
mouse right click, and click: query-tool
in this new query tool window, you can run your SQL without specifying set search_path to <SCHEMA_NAME>;
you can see the result:

Related

Undefined table: 7 ERROR: relation "V5TableName" does not exist

I am using an MVC framework (Zend) for my application and I want to find the total size of a table in PostgreSQL (including index). The table name is "V5TableName" - quotes included because table name is case sensitive. I have made sure that there is NO typo involved.
My code to get the table size is shown below:
public function getMyTableSize()
{
$sql = "SELECT pg_size_pretty(pg_total_relation_size( '\"V5TableName\"' ) );";
/* Custom_Db is a custom library in my application which makes the PostgreSQL connection
and queries the database
*/
$tableSize = Custom_Db::query($sql)->fetchColumn();
return $tableSize;
}
When my application calls this function it returns the following error in my logs :
[22-Apr-2020 09:42:37] PID:30849 ERR: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "V5TableName" does not exist
LINE 1: SELECT pg_size_pretty(pg_total_relation_size( '"V5TableName...
^
query was: SELECT pg_size_pretty(pg_total_relation_size( '"V5TableName"' ) );
If I run this same query in pgAdmin4 it works perfectly fine returning the table size (for instance: 104Mb).
I have tried:
Removing and adding quotes to the table name in the code.
Appending the schema as prefix to the table name (example: 'public."V5TableName"').
NONE of the above seem to work. I am not sure what is going wrong over here.
I also tried to find the total database size in my application (db name: MyDbName - with mixed case spelling) and my query looked something like below:
$sql = "SELECT pg_size_pretty(pg_database_size('MyDbName'))"; // this DID NOT WORK
So I changed it to the one shown below: (it worked)
$sql = "SELECT pg_size_pretty(pg_database_size( current_database() ))"; // this WORKED
I was wondering if there is something similar that could be done to find the table size.
Your query should work. The use of double-quotes seems correct.
SELECT pg_size_pretty(pg_total_relation_size('"V5TableName"'));
First make sure you are connecting to the right database cluster (a.k.a. "server"). It's defined by its data directory, or equally unambiguous by hostname and port number. Read the manual here and here.
Then make sure you are connecting to the right database within that database cluster. A Postgres database cluster consists of 1-n databases. When connecting without specifying the actual database, you end up in the maintenance database named postgres by default. That's the most likely explanation. Check with:
SELECT current_database();
Then check for the right table and schema name:
SELECT * FROM pg_tables
WHERE tablename ~* 'V5TableName'; -- ~* matches case-insensitive
The first riddle should be solved at this point.
Check your DB spelling and possible near-duplicates with:
SELECT datname FROM pg_database;
The call is without double-quotes (like you tried correctly), but requires correct capitalization:
SELECT pg_size_pretty(pg_database_size('MyDbName'));
Note the subtle difference (as documented in the manual):
pg_database_size() takes oid or name. So pass the case-sensitive database name without double-quotes.
pg_total_relation_size() takes regclass. So pass the case-sensitive relation name with double-quotes if you need to preserve capitalization.
pg_database_size() has to differ because there is no dedicated object identifier type for databases (no regdatabase).
The gist of it: avoid double-quoted identifiers in Postgres if at all possible. It makes your life easier.

Search using REPLACE in a SELECT with PDO and .MDB ACCESS, with PHP

I'm trying to write a mysql query that will match names from a table and the name in the database can contain dots or no dots. So, for example I would like my query string fast to match all of these: fast, f.ast, f.a.s.t etc.
I use PHP, with PDO connecting to a .MDB database.
I tried what I found here, with no success (I get error):
SELECT * FROM table WHERE replace(col_name, '.', '') LIKE "%fast%"
I think PDO for MDB databases is missing some functions :(
Any solution?
Thanks to Doug, I solved with:
$variable = implode("[.]", str_split($variable)) . "[.]";
and:
SELECT * FROM table
WHERE
col_name LIKE "%" . $variable ."%";
You cannot run the replace() function unless you are running the query through Access itself. You do however have a possible alternative, try the following:
SELECT * FROM table
WHERE
col_name LIKE "%fast%"
OR col_name LIKE "%f[.]a[.]s[.]t%";
The square brackets define an optional .
Or alternatively do it at PHP level with:
str_replace('.','',$var);

php sqlite - copy table to another database

I want to copy table from another db file but I fail and I can't get why. This is my code:
$db = new SQLite3($_SERVER['DOCUMENT_ROOT']."/db/098765.db");
$sql = "ATTACH DATABASE 'admin.db' AS admin ;
INSERT INTO 'table-1' SELECT * FROM 'admin.table-1';";
$db->query($sql);
I've read all the questions on this topic on this site, but no answer helped me.
Giving the full path to ATTACH DATABASE doesn't work. Creating table before inserting data also doesn't work.
The sqlite3 command line tool has a handy command called .dump that makes this task trivial:
sqlite3 admin.db '.dump "table-1"' | sqlite3 098765.db
This will create the table, all associated indexes and of course it will copy all the data.
Edit: For a more general solution, create a shell script (let's call it copy-table.sh) as follows:
#!/bin/bash
$src_db="$1"
$dst_db="$2"
$table="$3"
sqlite3 "$src_db" ".dump \"$table\"" | sqlite3 "$dst_db"
Then you can execute the script as follows
./copy-table.sh 'admin.db' '098765.db' 'table-1'
Obviously, you can execute the script anyway you want, e.g. from cron or from php.
Properly quote database object identifiers (table/column names etc) in your INSERT statement. Use use double quotes instead of single ones, which are for string literals. Better yet don't use dashes or other restricted characters in object names if possible (stick with alphanumerics and underscore).
Use exec() instead of query()
$dbPath = $_SERVER['DOCUMENT_ROOT'];
$adminDbPath = $dbPath; // Or something else
$db = new SQLite3("$dbPath/db/098765.db");
$db->exec("ATTACH DATABASE '$adminDbPath/admin.db' AS admin");
$db->exec('INSERT INTO "table-1" SELECT * FROM admin."table-1"');
^^^^ ^ ^ ^ ^
You can get exact copy of table by performing the following set of SQL statements:
(In context of connection to destination database)
attach '<source-db-full-name>' as sourceDb;
select sql from 'sqlite_master' where type = 'table' and name = '<name-of-table>';
// Execute result of previous statement.
// It will create empty table with
// schema identical to schema of source table
insert into '<name-of-table>' select * from sourceDb.[<name-of-table>];
detach sourceDb;

Query different MySQL tables from PHP

been googling for hours and I'm quite new to this.
I have two identical tables in one MySQL database:
One named "users" and one named "keys".
They are identical for testing purposes.
When I query "users" I get a response, when I query "keys" I get nothing.
Querying users I get the expected response:
<?php
require('../db/connect.php');
$query = mysql_query("
SELECT name
FROM users
WHERE can_share = '".$_POST['URLkey']."'
");
echo mysql_result($query, 0);
?>
Querying keys I get nothing:
<?php
require('../db/connect.php');
$query = mysql_query("
SELECT name
FROM keys
WHERE can_share = '".$_POST['URLkey']."'
");
echo mysql_result($query, 0);
?>
I guess there must be some basic understanding of databases that has slipped by me, but still, after hours of searching I can't figure it out. Maybe I'm becoming retarded.
I think that might be due to table name being 'keys'.
Have a look here:
http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html
You have to understand while designing your tables and naming the attributes that some words are reserved by MySQL itself.
So, if you name your table 'WHERE' you will have troubles in usual query. Why?
'SELECT * FROM WHERE'
Such a query obviously doesn't work, as it will ask you to provide table name.
Now, when you change format situation also changes:
'SELECT * FROM `WHERE`'
As you can see I added some backwards commas. In MySQL they are used to denote names of tables or fields. If you use them - the server processes and reads your query correctly.
So, that's why your edited query worked fine in the end.
Thanks to enabeling debugging, I got this message:
mysql_result() expects parameter 1 to be resource, boolean given in
...
And figured out that I had to query "keys" like this:
<?php
require('../db/connect.php');
$query = mysql_query("
SELECT `name`
FROM `keys`
WHERE `can_share` = '".$_POST['URLkey']."'
");
echo mysql_result($query, 0);
?>
Now it works, but I still don't understand why only one of the tables needed that formatting. And I have learned that I should rewrite the whole thing to not be vulnerable to SQL injection attacks. ...
EDIT: It seems like the words "key" and "keys" and some more are reserved by MySQL, so to use them, they have to be formatted like that.

MySQL error: Incorrect Table Name

I'm pretty new to web development so there's a good chance I'm doing something pretty dumb here.
I'm using AJAX to send data to a PHP file which will use the data to run SQL commands to update a table. I'm dealing with editing articles, so my PHP file needs to know three things: The original name of the article (for reference), the new name and the new content. I also tell it what page the user is looking at so it knows which table to edit.
$('#save_articles').click(function () {
var current_page = $('#current_location').html();
var array_details = {};
array_details['__current_page__'] = current_page;
$('#article_items .article_title').each(function(){
var article_name = $(this).html(); //The text in this div is the element name
var new_article_name = $(this).next('.article_content');
new_article_name = $(new_article_name).children('.article_content_title').html();
var new_article_content = $(this).next('.article_content');
new_article_content = $(new_article_content).children('.article_content_content').html();
array_new_deets = {new_name:new_article_name, content:new_article_content};
array_details[article_name] = array_new_deets;
});
send_ajax("includes/admin/admin_save_articles.php", array_details);
});
In the PHP file, I first retrieve the current page and store it in $sql_table and then remove the current page variable from $_POST. Then I run this.
foreach($_POST as $key => $value){
$original_name = $key;
$new_name = $value['new_name'];
$new_cont = $value['content'];
$query = "UPDATE
`$sql_table`
SET
`element_name`= '$new_name',
`element_content` = '$new_cont',
WHERE
`element_name` = '$original_name'";
$query = mysql_query($query);
if(!$query){
die(mysql_error());
}
}
I always receive an error saying that 'sitep_Home' is an incorrect table name. Not only is it a real table in my db, but I've actually changed its name to make sure it isn't an issue with keywords or something.
If I instead run the query without the variable $sql_table (specifying that the table is called 'sitep_Home'), the query accepts the table. It then doesn't actually update the table, and I suspect it's because of the WHERE argument that also uses a variable.
Can anyone see what I'm doing wrong here?
try to use $sql_table as '$sql_table' if you are sure that this contain a right table name.
Like you are using other column's value
Check if this can help!!
Dump/log your query before executing it - the problem should be quite visible after that (I suspect some additional characters in the table name).
Couple of things:
you should never trust your users and accept everything they'll send you in $_POST, use whitelist for the fields you'd like to update instead
your code is vulnerable to SQL injection, I recommend to use some framework / standalone library or PDO at least, avoid mysql_query which will be deprecated in the future. Check this to get some explanation http://www.phptherightway.com/#databases
Table names are case sensitive in MySQL. Please check if there is mistake in the case.
You have to surround name of mysql table in query in this `` qoutes. When you dinamically create mysql table it is very important to trim($variable of mysql name table) before create, because if "$variable of mysql name table" have space in the edns or in the start mysql not create table. And the last when you call dinamically $variable of mysql name table in query you have to trim($variable of mysql name table) again.

Categories