Lấy kiểu dữ liệu của từng cột từ bảng PostGIS?


9

Tôi cần lấy các kiểu dữ liệu cột của tất cả các cột trong một bảng, bao gồm các kiểu hình học. Những gì tôi muốn biết là nếu có một hàm hoặc SQL cung cấp một cái gì đó như thế này:

column_name | data_type
------------+--------------
gid         | integer
descr       | character varying(32)
class       | character varying(10)
area        | double precision
geom        | geometry(Polygon,3763)

Từ một vài câu trả lời trên stackexchangegis.stackexchange tôi biết rằng tôi có thể nhận được một số thông tin với truy vấn sau:

SELECT 
    g.column_name,
    g.data_type,
    g.character_maximum_length,
    g.udt_name,
    f.type,
    f.srid
FROM 
     information_schema.columns as g JOIN
     geometry_columns AS f 
         ON (g.table_schema = f.f_table_schema and g.table_name = f.f_table_name )
WHERE
    table_schema = 'my_schema_name' and
    table_name = 'my_table_name'

Kết quả:

column_name | data_type         | character_maximum_length | udt_name | type    | srid
------------+-------------------+--------------------------+----------+---------+------
gid         | integer           |                          |          |         |
descr       | character varying | 32                       |          |         |
class       | character varying | 10                       |          |         |
area        | double precision  |                          |
geom        | USER-DEFINED      |                          | geometry | Polygon | 3763

Nhưng, có cách nào thực tế hơn để lấy thông tin theo định dạng tôi cần không? Hoặc tôi phải nhập "thế giới" CASE WHENcấu trúc và nối chuỗi để thu thập tất cả các thuộc tính cột trong một cột theo định dạng đó?

Nỗi sợ hãi của tôi là nếu một loại dữ liệu không mong đợi làm tôi ngạc nhiên khi cần thuộc tính khác từ bảng information_schema.columns. Tức là, trong bảng ví dụ trước đây, tôi không sử dụng bất kỳ numeric (15,2)loại dữ liệu nào , mà sẽ cần sử dụng một thuộc tính khác (num_precision và num_scale) để được phân tích cú pháp bởi CASE WHEN.

Câu trả lời:


14

Lý thuyết là có, mặc dù bạn có thể thấy nó thực sự rất phức tạp.

  • Mỗi bảng (chọn * từ pg_group) có các cột.
  • Mỗi cột (chọn * từ pg_attribution) tùy ý có số "typmod".
  • Đối với các loại có typmod (chọn * từ pg_type) sẽ có chức năng "typmodout".
  • Chạy hàm typmod out trên một số typmod sẽ trả về một chuỗi có thể được nối với tên loại để tạo thành loại chữ ký dễ đọc mà bạn đã sử dụng (chọn 'số' | | numtypmodout (786441)) (chọn geography_typmodod (1107460))

Nhưng, này, psql tạo ra các chuỗi bạn muốn, nếu chúng ta nhìn vào SQL mà nó tạo ra, có thể câu trả lời nằm ở đó.

Chắc chắn, có một chức năng ma thuật lấy một loại typidod và typmod và trả về chuỗi ma thuật.

select a.attname, format_type(a.atttypid, a.atttypmod) from pg_attribute a where attname = 'geog';

Với sự tham gia vào pg_group, bạn sẽ có thể nhận được thông tin này trên mỗi bảng.


Tôi không nhận được bất kỳ kết quả nào where attname = 'geog'nhưng = 'geom'không hoạt động. Điều này mang lại cho tôi kết quả tốt cho các giá trị MultiPolygon, Point và MultiPoint nhưng tôi không thấy gì cho các loại Line hoặc MultiLine. Là những người được coi là đa giác?
mhkeller

7

Nó có thể được sử dụng một truy vấn SQL đơn giản.

SELECT * from information_schema.columns where table_name='mytablename'


1
Điều này làm việc tuyệt vời! Và đây là một mẹo: Đầu ra có thể dài, vì vậy bạn có thể muốn bật màn hình mở rộng trên bảng điều khiển của mình: \pset pagertắt trang, sau đó \xbật màn hình mở rộng.
modulitos

7

Với sự giúp đỡ của Paul Ramsey, tôi đã làm theo cách này:

SELECT a.attname as column_name, format_type(a.atttypid, a.atttypmod) AS data_type
FROM pg_attribute a
JOIN pg_class b ON (a.attrelid = b.relfilenode)
WHERE b.relname = 'my_table_name' and a.attstattarget = -1;

CẬP NHẬT

Trong khi đó tôi đã tạo một hàm để yêu cầu một kiểu dữ liệu cột nhất định

CREATE OR REPLACE FUNCTION "vsr_get_data_type"(_t regclass, _c text)
  RETURNS text AS
$body$
DECLARE
    _schema text;
    _table text;
    data_type text;
BEGIN
-- Prepare names to use in index and trigger names
IF _t::text LIKE '%.%' THEN
    _schema := regexp_replace (split_part(_t::text, '.', 1),'"','','g');
    _table := regexp_replace (split_part(_t::text, '.', 2),'"','','g');
    ELSE
        _schema := 'public';
        _table := regexp_replace(_t::text,'"','','g');
    END IF;

    data_type := 
    (
        SELECT format_type(a.atttypid, a.atttypmod)
        FROM pg_attribute a 
        JOIN pg_class b ON (a.attrelid = b.oid)
        JOIN pg_namespace c ON (c.oid = b.relnamespace)
        WHERE
            b.relname = _table AND
            c.nspname = _schema AND
            a.attname = _c
     );

    RETURN data_type;
END
$body$ LANGUAGE plpgsql;

Cách sử dụng là:

SELECT vsr_get_data_type('schema_name.table_name','column_name')

-1

nếu bạn muốn kiểm tra loại hình học, bạn có thể kiểm tra 'udt_name' trong 'Information_SCHema.COLUMNS' và sử dụng nó!:

select column_name,udt_name, data_type, character_maximum_length from INFORMATION_SCHEMA.COLUMNS where table_name =g

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.