Temp table creation issue in postgresql 11.6 - sql

In a PostgreSQL function I am creating a temp table named table1 in a loop.
To check if the table already exist in other iterations I use the query select * from pg_tables where tablename = '..'.
But if the table does not exist during iteration (dropped in between) it still says the table exist. Is there any way to check if the table exist in a query rather than the mentioned query?
Query sample
db=# select * from pg_tables where tablename = 'table1';
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers |rowsecurity
------------+-----------+------------+------------+------------+----------+-------------+-------------
pg_temp_3 | table1 | user1 |user1 _data1 | t | f | f | f
(1 row)
db=# \d table1
Did not find any relation named "table1".
This issue raises after the function is interrupted by an exception. Any suggestions or findings?

Related

In PostgreSQL, is it possible to query all the tables in a given database?

In PostgreSQL, is it possible to query all the tables in a given database for records that satisfy some condition?
Select [dbname "db"] *
From [all tables in database "db"]
Where [some condition on records]
The things inside [] are arbitrary up to what they are supposed to mean in general.
My best bet here is that you are wanting to return all rows from every table in a particular database that meet a certain condition. This gets tricky because:
It's necessary that the table upon which your condition is based be present in every table you are querying.
Furthermore, because your many tables in this one schema/database probably have different columns, you can't return them all in the same result set.
There is no "one" sql statement you can send to the database to do this. You will have to query at least twice. Once to get the list of tables, and once again to query those tables.
Consider a database/schema with two tables both with the column F1. We want all records from the tables in this schema where F1=1. So:
# CREATE TABLE public.t2 (f1 int, f2 varchar(20), f3 date);
CREATE TABLE
# CREATE TABLE public.t1 (f1 int, f4 varchar(40), f5 varchar(10), f6 int);
CREATE TABLE
# SELECT * FROM information_schema.tables WHERE table_schema = 'public';
table_catalog | table_schema | table_name | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into | is_typed | commit_action
---------------+--------------+------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------+----------+---------------
username | public | t2 | BASE TABLE | | | | | | YES | NO |
username | public | t1 | BASE TABLE | | | | | | YES | NO |
(2 rows)
# SELECT 'SELECT * FROM public.' || table_name || ' WHERE f1=1;' FROM
information_schema.tables WHERE table_schema = 'public';
?column?
-------------------------------------
SELECT * FROM public.t2 WHERE f1=1;
SELECT * FROM public.t1 WHERE f1=1;
(2 rows)
That last SQL generates two records (one for each table in the schema) querying it for records where your condition is true. You can now execute each of these separately to get your results (in two result sets).
# SELECT * FROM public.t2 WHERE f1=1;SELECT * FROM public.t1 WHERE f1=1;
f1 | f2 | f3
----+----+----
(0 rows)
f1 | f4 | f5 | f6
----+----+----+----
(0 rows)
If every table in your schema is exactly the same (same number of columns, order of columns, and data types) then you could query information_Schema and build a UNION query to then execute separately:
# CREATE TABLE public.t1 (f1 int, f2 varchar(20), f3 date);
CREATE TABLE
# CREATE TABLE public.t2 (f1 int, f2 varchar(20), f3 date);
CREATE TABLE
# INSERT INTO public.t1 VALUES (1, 'test', '2019-04-22'),(2, 'test2', '2019-04-22');
INSERT 0 2
# INSERT INTO public.t2 VALUES (1, 'testtest', '2019-04-21'),(2, 'testest2', '2019-04-20');
INSERT 0 2
# SELECT 'SELECT * FROM public.' || table_name || ' WHERE f1=1' || CASE WHEN LEAD(table_name) OVER (ORDER BY table_name) IS NOT NULL THEN ' UNION ALL' ELSE ';' END FROM information_schema.tables WHERE table_schema = 'public';
?column?
----------------------------------------------
SELECT * FROM public.t1 WHERE f1=1 UNION ALL
SELECT * FROM public.t2 WHERE f1=1;
(2 rows)
# SELECT * FROM public.t1 WHERE f1=1 UNION ALL
-# SELECT * FROM public.t2 WHERE f1=1;
f1 | f2 | f3
----+----------+------------
1 | test | 2019-04-22
1 | testtest | 2019-04-21
(2 rows)
You can see that neither option is pretty since you have to dynamically write SQL and then separately execute it.

How to delete hive table records ?

how to delete hive table records, we have 100 records there and i need to delete 10 records only,
when i use
dfs -rmr table_name whole table deleted
if any chance to delete in Hbase , send to data in Hbase,
You cannot delete directly from Hive table,
However, you can use a workaround of overwriting into Hive table
insert overwrite into table_name
select * from table_name
where id in (1,2,3,...)
You can't delete data from Hive tables since it is already written in the files in HDFS. You can only drop partitions which deletes directories in HDFS. So best practice is to have partitions if you want to delete in the future.
To delete records in a table, you can use the SQL syntax from your hive client :
DELETE FROM tablename [WHERE expression]
Try with where and your key with in clause
DELETE FROM tablename where id in (select id from tablename limit 10);
Example:-
I had acid transactional table in hive
select * from trans;
+-----+-------+--+
| id | name |
+-----+-------+--+
| 2 | hcc |
| 1 | hi |
| 3 | hdp |
+-----+-------+--+
Now i want to delete only 2 then my delete statement would be
delete from trans where id in (select id from trans limit 1);
Result:-
select * from trans;
+-----+-------+--+
| id | name |
+-----+-------+--+
| 1 | hi |
| 3 | hdp |
+-----+-------+--+
So we have just deleted the first record like this way you can specify limit 10 then hive can delete first 10 records.
you can specify orderby... some other clauses in your subquery if you need to delete only first 10 having specific order(like delete id's from 1 to 10).

SQL REGEX search for table name

this is my first entry, so please excuse me for any mistakes I might make writing this Post.
I have an oracle database schema full of Table Views. I want to use the "TEXT_VC" column in the "all_views" table to get a list of the source table names.
This is my statement so far:
SELECT view_name, text_vc, REGEXP_SUBSTR(TEXT_VC,'from (.+?) ') AS source_table
FROM all_views
WHERE owner = 'OWNER';
I still have a view problems with this regex.
First of all, I am getting "from table_name" as a result. I don't want to get "from" in my result set.
Secondly, the column TEXT_VC basically displays the SQL behind the view. So in some cases I don't get any results, because there are line breaks. I tried working with \n and \r but I am not able to generate the result I want.
Can anyone please help me?
select * from all_dependencies
Demo
create table mytable_1 (i int);
create table mytable_2 (i int);
create view myview
as
select count(*) as cnt
from mytable_1 t1
join mytable_2 t2
on t2.i = t1.i
;
select *
from all_dependencies
where owner = 'DMARKOVITZ'
and name = 'MYVIEW'
;
+------------+--------+------+------------------+-----------------+-----------------+----------------------+-----------------+
| OWNER | NAME | TYPE | REFERENCED_OWNER | REFERENCED_NAME | REFERENCED_TYPE | REFERENCED_LINK_NAME | DEPENDENCY_TYPE |
+------------+--------+------+------------------+-----------------+-----------------+----------------------+-----------------+
| DMARKOVITZ | MYVIEW | VIEW | DMARKOVITZ | MYTABLE_1 | TABLE | (null) | HARD |
| DMARKOVITZ | MYVIEW | VIEW | DMARKOVITZ | MYTABLE_2 | TABLE | (null) | HARD |
+------------+--------+------+------------------+-----------------+-----------------+----------------------+-----------------+

SQL Postgres Invalidate Rows that reference invalid Id's

I am trying to create a stored procedure that will invalidate rows that contain id references of an id in another table. The catch is that the rows to be invalidated contain groupings of these id's stored as a comma separated string. Let's take a look at the tables:
table_a table_b
+----+------+ +---------+-------+
| id | name | | ids | valid |
+----+------+ +---------+-------+
| 1 | a | | 1,2,3 | T |
| 2 | b | | 4,3,8 | T |
| 3 | c | | 5,2,5,4 | T |
| 4 | d | | 7 | T |
| 5 | e | | 6,8 | T |
| 6 | f | | 9,7,2 | T |
| 7 | g | +---------+-------+
| 8 | h |
+----+------+
Above you can see that table_b contains groupings of ids from table_a and as you can imagine the table_a.id is an integer while table_b.ids is text. The goal is to look at each table_b.ids and if it contains an id that does not exist in table_a.id then set its validity to false.
I have not worked with any SQL in quite sometime and I have never worked with PostgreSQL which is why I am having such difficulty. The closest query I could come up with, is not working, but is along the lines of:
CREATE FUNCTION cleanup_records() AS $func$
BEGIN
UPDATE table_b
SET valid = FALSE
WHERE COUNT(
SELECT regexp_split_to_table(table_b.ids)
EXCEPT SELECT id FROM table_a
) > 0;
END;
$func$ LANGUAGE PLPGSQL;
The general idea is that I am trying to turn each row of table_b.ids into a table and then using the EXCEPT operator against table_a to see if it has any ids that are invalid. The error I receive is:
ERROR: syntax error at or near "SELECT"
LINE 1: ...able_b SET valid = FALSE WHERE COUNT(SELECT reg...
which is not very helpful as it just indicates that I do not have the correct syntax. Is this query viable? If so can you show me where I may have gone wrong - if not is there an easier or even more complicated way to achieve this?
Sample data:
CREATE TABLE table_b
(ids text, valid boolean);
INSERT INTO table_b
(ids, valid)
VALUES
('1,2,3' , 'T'),
('4,3,8' , 'T'),
('5,2,5,4' , 'T'),
('7' , 'T'),
('6,8' , 'T'),
('9,7,2' , 'T');
CREATE TABLE table_a
(id integer, name text);
INSERT INTO table_a
(id, name)
VALUES
(1,'a'),
(2,'b'),
(3,'c'),
(4,'d'),
(5,'e'),
(6,'f'),
(7,'g'),
(8,'h');
UPDATE table_b
SET valid = FALSE
WHERE EXISTS(
SELECT regexp_split_to_table(table_b.ids)
EXCEPT SELECT id FROM table_a
);
You can use 'exists' to check for the existence of a row. The previous syntax was incorrect as count can't be used that way.
groupings of these id's stored as a comma separated string
Don't do that. It's really bad database design, and is why you're having problems. See:
Is using multiple foreign keys separated by commas wrong, and if so, why?
PostgreSQL list of integers separated by comma or integer array for performance?
Also, there's a more efficient way to do your query than that shown by vkp. If you do it that way, you're splitting the string for every ID you're testing. There is no need to do that. Instead, join on a table of expanded ID lists.
Something like:
UPDATE table_b
SET valid = 'f'
FROM table_b b
CROSS JOIN regexp_split_to_table(b.ids, ',') b_ids(id)
LEFT JOIN table_a a ON (a.id = b_ids.id::integer)
WHERE table_b.ids = b.ids
AND a.id IS NULL
AND table_b.valid = 't';
You need to join on table_b even though it's the update target because you can't make a lateral function reference to the update target table directly.

Create SQL table with the data from another table

How do I create a table using data which is already present in another table (copy of table)?
The most portable means of copying a table is to:
Create the new table with a CREATE TABLE statement
Use INSERT based on a SELECT from the old table:
INSERT INTO new_table
SELECT * FROM old_table
In SQL Server, I'd use the INTO syntax:
SELECT *
INTO new_table
FROM old_table
...because in SQL Server, the INTO clause creates a table that doesn't already exist.
If you are using MySQL, you may want to use the CREATE TABLE ... AS SELECT syntax to create a table defined by the columns and data types of another result set:
CREATE TABLE new_table AS
SELECT *
FROM old_table;
Example:
CREATE TABLE old_table (id int, value int);
INSERT INTO old_table VALUES (1, 100), (2, 200), (3, 300), (4, 400);
CREATE TABLE new_table AS
SELECT *
FROM old_table;
SELECT * FROM new_table;
+------+-------+
| id | value |
+------+-------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
| 4 | 400 |
+------+-------+
4 rows in set (0.00 sec)
DESCRIBE new_table;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| value | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.03 sec)
For other DBMSes, that do not support this syntax, you may want to check out #OMG Ponies' answer for a more portable solution.
For SQL Server
SELECT *
INTO NewTable
FROM OldTable
For Sql server:
Create new table from existing table :
CREATE TABLE new_table_name AS
SELECT [col1,col2,...coln] FROM existing_table_name [WHERE condition];
Insert values into existing table form another existing table using Select command :
SELECT * INTO destination_table FROM source_table [WHERE conditions];
SELECT *
INTO newtable [IN externaldb]
FROM oldtable
[ WHERE condition ];
Insert values into existing table form another existing table using
Insert command :
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1,column2, column3, ... FROM table1 [WHERE condition];
if u want exact schema of existing table to new table and all values of existing table want to be inserted into your new table then execute below two queries :
create table new_table_name like Old_table_name;
select * into new_table_name from Old_table_name;
LIKE works only for base tables, not for views.
If the original table is a TEMPORARY table, CREATE TABLE ... LIKE does not preserve TEMPORARY. To create a TEMPORARY destination table, use CREATE TEMPORARY TABLE ... LIKE.
for more details click here