powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Выбрать список таблиц не через psql-шел
11 сообщений из 11, страница 1 из 1
Выбрать список таблиц не через psql-шел
    #34497451
Skif Swarogich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сабж.
Мне надо постоянно в моих функциях получать список таблиц в базе. \dt не подходит. Как через SQL получить?
Сейчас пользую:

Код: plaintext
SELECT tablename FROM pg_tables WHERE tableowner='owner'
но это не удобно.
При инсталяции функций и процедур приходиться каждый раз править их содержимое на предмет владельца.
В MySQL есть хорошая функция
Код: plaintext
SHOW TABLES
Которая с минимальными потерями позволяет решить мою задачу.
В принципе, мне, как вариант, подошла бы и проверка на существование необходимой таблицы. Есть хотя бы такое?
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497468
моррут
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ключ -E у psql покажет что он шлёт на стервер при \dt
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497469
BlackDan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Очень мало в посте полезной информации, больше эмоций :)
Skif SwarogichСабж.
Мне надо постоянно в моих функциях получать список таблиц в базе. \dt не подходит. Как через SQL получить?
Сейчас пользую:
Код: plaintext
SELECT tablename FROM pg_tables WHERE tableowner='owner'
но это не удобно.в чем, собственно, неудобство?

авторВ MySQL есть хорошая функция
Код: plaintext
SHOW TABLES
Которая с минимальными потерями позволяет решить мою задачу.

Чем show tables принципиально отличается от select * from pg_tables ?

авторВ принципе, мне, как вариант, подошла бы и проверка на существование необходимой таблицы. Есть хотя бы такое?
Код: plaintext
SELECT tablename FROM pg_tables WHERE tablename = 'tablename'
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497508
MBG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MBG
Гость
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  foreach x [list table_1 view_1] {
    spi_exec -array V "SELECT relname, pg_class.relkind as relkind FROM pg_class, pg_namespace \
      WHERE pg_class.relnamespace=pg_namespace.oid \
        AND pg_class.relkind IN ('v', 'r') \
        AND pg_namespace.nspname='user_$1' \
        AND relname = '$unit\_$x'" {
      if [info exists V(relname)] {
        if {$V(relkind) eq "v"} {
          spi_exec "DROP VIEW  user_$1.$V(relname) CASCADE"
        }
        if {$V(relkind) eq "r"} {
          spi_exec "DROP TABLE  user_$1.$V(relname) CASCADE"
        }
      }
    }
  }


Доступно объяснил?
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497523
Skif Swarogich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlackDanОчень мало в посте полезной информации, больше эмоций :)
в чем, собственно, неудобство?

авторВ MySQL есть хорошая функция
Код: plaintext
SHOW TABLES
Которая с минимальными потерями позволяет решить мою задачу.

Чем show tables принципиально отличается от select * from pg_tables ?

авторВ принципе, мне, как вариант, подошла бы и проверка на существование необходимой таблицы. Есть хотя бы такое?
Код: plaintext
SELECT tablename FROM pg_tables WHERE tablename = 'tablename'


не удобно тем, что владелец меняется. схема по дефолту public. На сервере может находиться несколько похожих баз (например одна основная, а вторая развернутая из бекапа), в результате таблиц с одинаковым названием может быть или несколько или не в той базе что не обходимо. Плюс могут находиться другие базы, которые могут содержать схожие названия таблиц. Так что у меня пока из всего что есть только и остается выбор из pg_tables по схеме и владельцу :( Увы, другого пока не знаю способа.
А SHOW TABLES принципиально отличается от SELECT tablename FROM pg_tables тем, что ей нет нужды во вспомогательных данных, как-то имя таблицы откуда выбирать, схемы, владельца таблиц/схем. Все делается достаточно просто без излишнего головомойства.
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497525
Skif Swarogich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MBG
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  foreach x [list table_1 view_1] {
    spi_exec -array V "SELECT relname, pg_class.relkind as relkind FROM pg_class, pg_namespace \
      WHERE pg_class.relnamespace=pg_namespace.oid \
        AND pg_class.relkind IN ('v', 'r') \
        AND pg_namespace.nspname='user_$1' \
        AND relname = '$unit\_$x'" {
      if [info exists V(relname)] {
        if {$V(relkind) eq "v"} {
          spi_exec "DROP VIEW  user_$1.$V(relname) CASCADE"
        }
        if {$V(relkind) eq "r"} {
          spi_exec "DROP TABLE  user_$1.$V(relname) CASCADE"
        }
      }
    }
  }


Доступно объяснил?
немного не понял. Откуда берутся 'user_$1' '$unit\_$x'
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497529
Skif Swarogich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
моррутключ -E у psql покажет что он шлёт на стервер при \dt
Вот это кажется именно оно. Спасибо, буду пробовать.
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34497724
MBG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MBG
Гость
'user_$1' и '$unit\_$x' - это просто переменные, а сам sql-запрос ищет в указанной схеме указанные таблицы и виды и удаляет их, если находит.

А пример я взял вот из такой функции:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
CREATE OR REPLACE FUNCTION reports.build_sales_checks(int4)
  RETURNS bool AS
$BODY$
 
  set unit report_sales_checks
  set session_table "user_$1.session"
  set db_prefix "user_$1.$unit\_"
 
  spi_exec "DELETE from $session_table where unit='$unit' and var IN ('db_log', 'db_sale_filter', 'db_user_filter', 'db_date_filter')"
  # drop views
  foreach x [list checks expand_checks] {
    spi_exec -array V "SELECT relname, pg_class.relkind as relkind FROM pg_class, pg_namespace \
      WHERE pg_class.relnamespace=pg_namespace.oid \
        AND pg_class.relkind IN ('v', 'r') \
        AND pg_namespace.nspname='user_$1' \
        AND relname = '$unit\_$x'" {
      if [info exists V(relname)] {
        if {$V(relkind) eq "v"} {
          spi_exec "DROP VIEW  user_$1.$V(relname) CASCADE"
        }
        if {$V(relkind) eq "r"} {
          spi_exec "DROP TABLE  user_$1.$V(relname) CASCADE"
        }
      }
    }
  }
 
  set sql_get {SELECT value from $session_table where unit='$unit' and var='$var'}
 
  set vars [list macroregion region dealer subdealer category cluster trademark]
  set sale_filter true
  foreach var $vars {
    if {![ spi_exec [subst $sql_get]]} {
      set log [quote "Ошибка: Не найден элемент $var в переменных сессии модуля $unit"]
      spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_log', '$log')"
      return false
    } 
    if {$value ne ""} {
      append sale_filter " and $var IN ([joinquote $value])"
    }
  }
  spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_sale_filter', '[quote $sale_filter]')"
 
  set var user
  set user_filter true
  if {![ spi_exec [subst $sql_get]]} {
      set log [quote "Ошибка: Не найден элемент $var в переменных сессии модуля $unit"]
      spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_log', '$log')"
      return false
  }
  if {$value ne ""} {
    set user_filter "name IN ([joinquote $value])"
  }
  spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_user_filter', '[quote $user_filter]')"
 
  set vars [list date_from date_to]
  set sql_get {SELECT value from $session_table where unit='$unit' and var='$var'}
  foreach var $vars {
    if {![ spi_exec [subst $sql_get]]} {
      set log [quote "Ошибка: Не найден элемент $var в переменных сессии модуля $unit"]
      spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_log', '$log')"
      return false
    } 
    if {$value ne ""} {
      set $var [quote $value]
    } else {
      set log [quote "Ошибка: Пустое значение элемента $var в переменных сессии модуля $unit"]
      spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_log', '$log')"
      return false
    }
  }
 
  # если дошли до этого места, фильтры по т/т и пользователю успешно созданы, можно начинать генерацию таблиц отчета
 
  spi_exec "create view ${db_prefix}checks as 
    select distinct check_date, object_id, user_id
    from cache.checks d 
    where d.check_date between '$date_from'::date and '$date_to'::date 
    and d.object_id IN (select id from merch.objects_sales where $sale_filter) 
    and d.user_id   IN (select id from auth.users       where $user_filter)"
 
  spi_exec "CREATE view ${db_prefix}expand_checks AS
SELECT s.id as object_id, macroregion, region, case when s.code='' then 'Удалена' else s.code end as code,
    town, address, dealer, subdealer, category, cluster,
    trademark, person, phone, u.id as user_id, u.name as user,
    check_date
FROM ${db_prefix}checks c
left join merch.objects_sales s on c.object_id=s.id
left join auth.users u on c.user_id  =u.id"
 
  # таблицы отчета построены, возвращаем управление
  spi_exec "INSERT INTO $session_table (unit, var, value) values ('$unit', 'db_log', '')"
  return true
 
$BODY$
  LANGUAGE 'pltcl' VOLATILE SECURITY DEFINER;
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34498025
BlackDan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MBG
LANGUAGE 'pltcl' VOLATILE SECURITY DEFINER;
[/src]
спасибо, всё всем понятно... все используют в разработке pltcl, знают конструкции языка и т.д. и т.п.
возможно, для ответа на любой вопрос, достаточно привести код на каком-нибудь экзотическом языке, чтобы всем стало всё понятно и вопросов больше не возникало... отличная практика.
дааа!!! ещё у меня есть фукции на 1000 строк, возможно, я их должен тоже на форум запостить, чтобы решить половину проблем спрашивающих?!
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34498511
MBG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MBG
Гость
Я привел пример SQL кода. В ответ на вопрос подробно показал, где этот код используется. Если ты не можешь найти SQL код в приведенном фрагменте, вряд ли кто тебе сможет помочь.
...
Рейтинг: 0 / 0
Выбрать список таблиц не через psql-шел
    #34500814
Skif Swarogich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Люди, спасибо, все решилось при помощи ключика -E и просмотра запроса. В итоге написал свою функцию на plperl.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
CREATE or REPLACE FUNCTION show_tables(varchar) returns setof varchar AS '

my $tbl_scheme = shift @_;
my $query="SELECT n.nspname as  Scheme ,
  c.relname as Name,
  CASE c.relkind WHEN ''r'' THEN ''Table'' WHEN ''v'' THEN ''View'' WHEN ''i'' THEN ''Index'' WHEN ''S'' THEN ''Posled'' WHEN ''s'' THEN ''Spesial'' END as Type,
  r.rolname as Owner
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_roles r ON r.oid = c.relowner
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN (''r'','''')
      AND n.nspname NOT IN (''pg_catalog'', ''pg_toast'')
      AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2";
my $dbh  = spi_exec_query($query);
my $rows = $dbh->{processed};
my $res  = $dbh->{status};

my @res_data;
foreach my $rw (0 .. ($rows - 1)) {
	my $rs = $dbh->{rows}[$rw];
	my $scheme = $rs->{scheme};
	my $name = $rs->{name};
	my $type = $rs->{type};
	my $owner = $rs->{owner};
	if (($type eq "Table") and ($scheme eq $tbl_scheme)) {
		push @res_data, $name;
	}
}
foreach my $table (@res_data) {
	return_next($table);
}

return undef;
'
LANGUAGE 'plperl';
Ключевое во всем этом сам запрос, подсмотренный у шела psql:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT n.nspname as  Scheme ,
  c.relname as Name,
  CASE c.relkind WHEN ''r'' THEN ''Table'' WHEN ''v'' THEN ''View'' WHEN ''i'' THEN ''Index'' WHEN ''S'' THEN ''Posled'' WHEN ''s'' THEN ''Spesial'' END as Type,
  r.rolname as Owner
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_roles r ON r.oid = c.relowner
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN (''r'','''')
      AND n.nspname NOT IN (''pg_catalog'', ''pg_toast'')
      AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY  1 , 2 
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Выбрать список таблиц не через psql-шел
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]