(8.0.32)
drop procedure ddl2json;
delimiter //
create procedure ddl2json(
in p_schema_name varchar(4000)
, in p_table_name varchar(4000)
)
begin
declare v_comments varchar(4000);
declare v_partition_type varchar(4000);
declare v_partition_key varchar(4000);
declare i_col_count integer;
declare i_partition_count integer;
declare i_primary_count integer;
declare i_index_count integer;
declare v_wk1 varchar(4000);
declare v_wk2 varchar(4000);
declare v_wk3 varchar(4000);
declare v_wk4 varchar(4000);
declare v_wk5 varchar(4000);
declare v_wk6 varchar(4000);
declare v_wk7 varchar(4000);
declare i_wk1 bigint;
declare i_wk2 bigint;
declare i_wk3 bigint;
declare i_wk4 bigint;
-- カーソル関連
declare done int;
declare cur2 cursor for select ordinal_position
, column_name
, data_type
, character_maximum_length
, numeric_precision
, numeric_scale
, is_nullable
, column_comment
from information_schema.columns
where table_schema= p_schema_name
and table_name = p_table_name
order by ordinal_position
;
declare cur3 cursor for select partition_ordinal_position
, partition_name
, partition_description
from information_schema.partitions
where table_schema= p_schema_name
and table_name = p_table_name
order by partition_ordinal_position
;
declare cur4 cursor for select index_name,group_concat(concat('"',column_name,'"') order by seq_in_index separator ',') column_name
from information_schema.statistics
where table_schema = p_schema_name
and table_name = p_table_name
and index_name = 'PRIMARY'
group by index_name
order by index_name
;
declare cur5 cursor for select index_name,non_unique,group_concat(concat('"',column_name,'"') order by seq_in_index separator ',') column_name
from information_schema.statistics
where table_schema = p_schema_name
and table_name = p_table_name
and index_name != 'PRIMARY'
group by index_name,non_unique
order by index_name,non_unique
;
declare continue handler for sqlstate '02000' set done = 1;
-- テンポラリテーブルを作成し、JSON情報を格納する
drop temporary table if exists ttab1;
create temporary table ttab1(col1 int not null auto_increment primary key,col2 varchar(4000) );
insert into ttab1(col2) values('{');
insert into ttab1(col2) values(concat(' "schema_name": "',p_schema_name,'",') );
insert into ttab1(col2) values(concat(' "table_name": "',p_table_name,'",') );
-- テーブルコメント情報
set v_comments = ( select table_comment
from information_schema.tables
where table_schema = p_schema_name
and table_name = p_table_name );
insert into ttab1(col2) values(concat(' "table_desc": "',v_comments,'",') );
-- カラム情報
set i_col_count = ( select count(*)
from information_schema.columns
where table_schema= p_schema_name
and table_name = p_table_name );
insert into ttab1(col2) values(' "cols": [');
set done = 0;
open cur2;
fetch cur2 into i_wk1
, v_wk1
, v_wk2
, i_wk2
, i_wk3
, i_wk4
, v_wk3
, v_wk4;
while done != 1 do
if i_wk1 != i_col_count then
set v_wk5 = ',';
else
set v_wk5 = '';
end if;
if v_wk3 = 'NO' then
set v_wk6 = 'true';
else
set v_wk6 = 'false';
end if;
case
when v_wk2 in ('int','bigint','datetime') then
set v_wk7 = v_wk2;
when v_wk2 = 'decimal' then
set v_wk7 = concat(v_wk2,'(',cast(i_wk3 as char),',',cast(i_wk4 as char),')');
when v_wk2 = 'varchar' then
set v_wk7 = concat(v_wk2,'(',cast(i_wk2 as char),')');
else
select 'unsupported data type found';
end case;
insert into ttab1(col2) values(concat(' { "col_name": "',v_wk1,'", "col_type": "',v_wk7,'", "not_null": "',v_wk6,'", "col_desc": "',v_wk4,'" }',v_wk5) );
fetch cur2 into i_wk1
, v_wk1
, v_wk2
, i_wk2
, i_wk3
, i_wk4
, v_wk3
, v_wk4;
end while;
close cur2;
insert into ttab1(col2) values(' ],');
-- パーティション情報
set i_partition_count = ( select count(*)
from information_schema.partitions
where table_schema= p_schema_name
and table_name = p_table_name
and partition_method is not null );
if i_partition_count = 0 then
insert into ttab1(col2) values(' "partition": {},');
else
-- パーティションタイプとパーティションキー取得
set v_partition_type = ( select partition_method
from information_schema.partitions
where table_schema= p_schema_name
and table_name = p_table_name
limit 1 );
insert into ttab1(col2) values(' "partition": {');
insert into ttab1(col2) values(concat(' "partition_type": "',v_partition_type,'",') );
set v_partition_key = ( select replace(partition_expression,'`','')
from information_schema.partitions
where table_schema= p_schema_name
and table_name = p_table_name
limit 1 );
insert into ttab1(col2) values(concat(' "partition_col": "',v_partition_key,'",') );
insert into ttab1(col2) values(' "partition_defs" : [');
-- パーティション定義情報
set done = 0;
open cur3;
fetch cur3 into i_wk1
,v_wk1
,v_wk2;
while done != 1 do
if i_wk1 != i_partition_count then
set v_wk3 = ',';
else
set v_wk3 = '';
end if;
if v_partition_type = 'RANGE COLUMNS' then
insert into ttab1(col2) values(concat(' { "partition_name": "',v_wk1,'", "partition_limit": "',v_wk2,'" }',v_wk3) );
elseif v_partition_type = 'LIST COLUMNS' then
insert into ttab1(col2) values(concat(' { "partition_name": "',v_wk1,'", "partition_limit": "(',v_wk2,')" }',v_wk3) );
elseif v_partition_type = 'HASH' then
insert into ttab1(col2) values(concat(' { "partition_name": "',v_wk1,'" }',v_wk3) );
else
select 'unsupported partition type found';
end if;
fetch cur3 into i_wk1
,v_wk1
,v_wk2;
end while;
close cur3;
insert into ttab1(col2) values(' ]');
insert into ttab1(col2) values(' },');
end if;
-- 主キー情報
set i_primary_count = ( select count(*)
from information_schema.statistics
where table_schema = p_schema_name
and table_name = p_table_name
and index_name = 'PRIMARY');
if i_primary_count = 0 then
insert into ttab1(col2) values(' "primary": {},');
else
set done = 0;
open cur4;
fetch cur4 into v_wk1
, v_wk2;
while done != 1 do
insert into ttab1(col2) values(concat(' "primary": { "constraint_name": "',concat(p_table_name,'pk'),'", "index_cols": [',v_wk2,'] },') );
fetch cur4 into v_wk1
, v_wk2;
end while;
close cur4;
end if;
-- インデックス情報
set i_index_count = ( select count(distinct index_name)
from information_schema.statistics
where table_schema = p_schema_name
and table_name = p_table_name
and index_name != 'PRIMARY'
);
if i_index_count = 0 then
insert into ttab1(col2) values(' "indexes": []');
else
insert into ttab1(col2) values(' "indexes": [');
set i_wk2 = 0;
set done = 0;
open cur5;
fetch cur5 into v_wk1
, i_wk1
, v_wk2;
while done != 1 do
set i_wk2 = i_wk2+1;
if i_wk2 != i_index_count then
set v_wk3 = ',';
else
set v_wk3 = '';
end if;
if i_wk1 = 0 then
set v_wk4 = 'true';
else
set v_wk4 = 'false';
end if;
insert into ttab1(col2) values(concat(' { "index_name": "',v_wk1,'", "index_cols": [',v_wk2,'] ,"unique": "',v_wk4,'"}',v_wk3) );
fetch cur5 into v_wk1
, i_wk1
, v_wk2;
end while;
close cur5;
insert into ttab1(col2) values(' ]');
end if;
insert into ttab1(col2) values('}');
select col2 from ttab1 order by col1;
end
//
delimiter ;
call ddl2json('test','tab1');
call ddl2json('test','tab2');
call ddl2json('test','tab3');
call ddl2json('test','tab4');
MYSQL_PWD='password' mysql -N -B -uroot test <<EOF > tab1.json
call ddl2json('test','tab1');
EOF
- Oracle
(19c)
set serveroutput on format wrapped
create or replace procedure ddl2json(
p_schema_name in varchar2 default 'TEST'
,p_table_name in varchar2 default 'TAB1'
) as
v_comments all_tab_comments.comments%type;
v_partition_type all_part_tables.partitioning_type%type;
v_partition_key all_part_key_columns.column_name%type;
i_col_count integer;
i_partition_count integer;
i_primary_count integer;
i_index_count integer;
v_wk1 varchar2(4000);
v_wk2 varchar2(4000);
v_wk3 varchar2(4000);
i_wk1 integer;
begin
dbms_output.put_line('{');
dbms_output.put_line(' "schema_name": "'||p_schema_name||'",');
dbms_output.put_line(' "table_name": "'||p_table_name||'",');
-- テーブルコメント情報
v_comments:='';
for c1 in (select comments
from all_tab_comments
where owner = p_schema_name
and table_name = p_table_name ) loop
v_comments:= c1.comments;
end loop;
dbms_output.put_line(' "table_desc": "'||v_comments||'",');
-- カラム情報
select count(*) into i_col_count
from all_tab_cols
where owner = p_schema_name
and table_name = p_table_name ;
dbms_output.put_line(' "cols": [');
for c2 in ( select t1.column_id,t1.column_name,t1.data_type,t1.data_length,t1.data_precision,t1.data_scale,t1.nullable,t2.comments
from all_tab_cols t1
left outer join all_col_comments t2
on t1.owner = t2.owner
and t1.table_name = t2.table_name
and t1.column_name = t2.column_name
where t1.owner = p_schema_name
and t1.table_name = p_table_name
order by t1.column_id ) loop
if c2.column_id != i_col_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if c2.nullable = 'N' then
v_wk2:= 'true';
else
v_wk2:= 'false';
end if;
case
when c2.data_type = 'NUMBER' AND c2.data_precision is null then
v_wk3 := c2.data_type;
when c2.data_type = 'NUMBER' AND c2.data_precision is not null and c2.data_scale is null then
v_wk3 := c2.data_type||'('||c2.data_precision||')';
when c2.data_type = 'NUMBER' AND c2.data_precision is not null and c2.data_scale is not null then
v_wk3 := c2.data_type||'('||c2.data_precision||','||c2.data_scale||')';
when c2.data_type like '%CHAR%' then
v_wk3 := c2.data_type||'('||c2.data_length||')';
when c2.data_type like '%TIMESTAMP%' then
v_wk3 := c2.data_type;
else
dbms_output.put_line('unsupported data type found');
end case;
dbms_output.put_line(' { "col_name": "'||c2.column_name||'", "col_type": "'||v_wk3||'", "not_null": "'||v_wk2||'", "col_desc": "'||c2.comments||'" }'||v_wk1);
end loop;
dbms_output.put_line(' ],');
-- パーティション情報
select count(*) into i_partition_count
from all_tab_partitions
where table_owner = p_schema_name
and table_name = p_table_name ;
if i_partition_count = 0 then
dbms_output.put_line(' "partition": {},');
else
-- パーティションタイプとパーティションキー取得
select partitioning_type into v_partition_type
from all_part_tables
where owner = p_schema_name
and table_name = p_table_name ;
dbms_output.put_line(' "partition": {');
dbms_output.put_line(' "partition_type": "'||v_partition_type||'",');
select column_name into v_partition_key
from all_part_key_columns
where owner = p_schema_name
and name = p_table_name ;
dbms_output.put_line(' "partition_col": "'||v_partition_key||'",');
dbms_output.put_line(' "partition_defs" : [');
-- パーティション定義情報
for c3 in ( select partition_position,partition_name,high_value from all_tab_partitions
where table_owner = p_schema_name
and table_name = p_table_name
order by partition_position
) loop
if c3.partition_position != i_partition_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if v_partition_type = 'RANGE' then
dbms_output.put_line(' { "partition_name": "'||c3.partition_name||'", "partition_limit": "'||c3.high_value||'" }'||v_wk1);
elsif v_partition_type = 'LIST' then
dbms_output.put_line(' { "partition_name": "'||c3.partition_name||'", "partition_limit": "('||c3.high_value||')" }'||v_wk1);
elsif v_partition_type = 'HASH' then
dbms_output.put_line(' { "partition_name": "'||c3.partition_name||'" }'||v_wk1);
else
dbms_output.put_line('unsupported partition type found');
end if;
end loop;
dbms_output.put_line(' ]');
dbms_output.put_line(' },');
end if;
-- 主キー情報
select count(*) into i_primary_count
from all_constraints
where owner = p_schema_name
and table_name = p_table_name
and constraint_type='P' ;
if i_primary_count = 0 then
dbms_output.put_line(' "primary": {},');
else
for c4 in ( select t2.constraint_name,listagg('"'||t1.column_name||'"',',') within group ( order by t1.column_position) column_name
from all_ind_columns t1
inner join all_constraints t2
on t1.table_owner = t2.owner
and t1.table_name = t2.table_name
and t2.constraint_type = 'P'
and t1.index_name = t2.index_name
where t1.table_owner = p_schema_name
and t1.table_name = p_table_name
group by t2.constraint_name ) loop
dbms_output.put_line(' "primary": { "constraint_name": "'||c4.constraint_name||'", "index_cols": ['||c4.column_name||'] },');
end loop;
end if;
-- インデックス情報
select count(*) into i_index_count
from all_indexes t1
where t1.table_owner = p_schema_name
and t1.table_name = p_table_name
and not exists ( select 1 from all_constraints t2
where t2.owner = t1.table_owner
and t2.table_name = t1.table_name
and t2.index_name = t1.index_name
and t2.constraint_type='P'
);
if i_index_count = 0 then
dbms_output.put_line(' "indexes": []');
else
dbms_output.put_line(' "indexes": [');
i_wk1:= 0;
for c5 in ( select t1.index_name,t1.uniqueness ,listagg('"'||t2.column_name||'"',',') within group ( order by t2.column_position) column_name
from all_indexes t1
inner join all_ind_columns t2
on t1.table_owner = t2.table_owner
and t1.table_name = t2.table_name
and t1.index_name = t2.index_name
where t1.table_owner = p_schema_name
and t1.table_name = p_table_name
and not exists ( select 1 from all_constraints t3
where t3.owner = t1.table_owner
and t3.table_name = t1.table_name
and t3.index_name = t1.index_name
and t3.constraint_type='P'
)
group by t1.index_name,t1.uniqueness ) loop
i_wk1 := i_wk1+1;
if i_wk1 != i_index_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if c5.uniqueness = 'UNIQUE' then
v_wk2:= 'true';
else
v_wk2:= 'false';
end if;
dbms_output.put_line(' { "index_name": "'||c5.index_name||'", "index_cols": ['||c5.column_name||'] ,"unique": "'||v_wk2||'"}'||v_wk1);
end loop;
dbms_output.put_line(' ]');
end if;
dbms_output.put_line('}');
end;
/
sho error;
exec ddl2json
exec ddl2json('TEST','TAB1');
exec ddl2json('TEST','TAB2');
exec ddl2json('TEST','TAB3');
exec ddl2json('TEST','TAB4');
sqlplus -s test/test@pdb1 <<EOF > tab1.json
set serveroutput on format wrapped
set feed off
exec ddl2json('TEST','TAB1');
EOF
- PostgreSQL
(15)
drop procedure ddl2json;
create or replace procedure ddl2json(
p_schema_name in varchar default 'public'
, p_table_name in varchar default 'tab1'
)
language plpgsql
as $$
declare
v_comments varchar(4000);
v_partition_type varchar(4000);
v_partition_key varchar(4000);
i_col_count integer;
i_partition_count integer;
i_primary_count integer;
i_index_count integer;
v_wk1 varchar(4000);
v_wk2 varchar(4000);
v_wk3 varchar(4000);
i_wk1 integer;
r record;
begin
raise notice '{';
raise notice ' "schema_name": "%",' ,p_schema_name;
raise notice ' "table_name": "%",' ,p_table_name;
-- テーブルコメント情報
for r in ( select obj_description ( oid ,'pg_class') comments
from pg_class
where relname = p_table_name
and relnamespace = p_schema_name::regnamespace) loop
v_comments:= r.comments;
end loop;
raise notice ' "table_desc": "%",' ,v_comments;
-- カラム情報
select count(*) strict into i_col_count
from information_schema.columns
where table_catalog = current_database()
and table_schema = p_schema_name
and table_name = p_table_name
;
raise notice ' "cols": [';
for r in ( select t2.ordinal_position
, t2.column_name
, t2.data_type
, t2.character_maximum_length
, t2.numeric_precision
, t2.numeric_scale
, t2.is_nullable
, col_description ( t1.oid ,t2.ordinal_position ) description
from pg_class t1
inner join information_schema.columns t2
on t1.relname = t2.table_name
where t1.relname = p_table_name
and t1.relnamespace = p_schema_name::regnamespace
and t2.table_catalog='test'
and t2.table_schema = p_schema_name
order by t2.ordinal_position ) loop
if r.ordinal_position != i_col_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if r.is_nullable = 'NO' then
v_wk2:= 'true';
else
v_wk2:= 'false';
end if;
case
when r.data_type in ('integer','bigint') then
v_wk3 := r.data_type;
when r.data_type = 'numeric' then
v_wk3 := r.data_type||'('||r.numeric_precision||','||r.numeric_scale||')';
when r.data_type like '%character%' then
v_wk3 := r.data_type||'('||r.character_maximum_length||')';
when r.data_type like '%timestamp%' then
v_wk3 := r.data_type;
else
raise notice 'unsupported data type found';
end case;
raise notice ' { "col_name": "%", "col_type": "%", "not_null": "%", "col_desc": "%" }%' ,r.column_name, v_wk3, v_wk2, r.description, v_wk1;
end loop;
raise notice ' ],';
-- パーティション情報
select count(*) strict into i_partition_count
from pg_inherits
where inhparent in (select oid
from pg_class
where relname = p_table_name
and relnamespace = p_schema_name::regnamespace
)
;
if i_partition_count = 0 then
raise notice ' "partition": {},';
else
-- パーティションタイプとパーティションキー取得
select case partstrat
when 'r' then 'range'
when 'l' then 'list'
when 'h' then 'hash'
else 'unknown'
end strict into v_partition_type
from pg_partitioned_table
where partrelid in (select oid
from pg_class
where relname = p_table_name
and relnamespace = p_schema_name::regnamespace
)
;
raise notice ' "partition": {';
raise notice ' "partition_type": "%",' ,v_partition_type;
select t1.attname strict into v_partition_key
from pg_attribute t1
where t1.attrelid in (select oid
from pg_class
where relname = p_table_name
and relnamespace = p_schema_name::regnamespace
)
and t1.attnum in (
select unnest(string_to_array(partattrs::text, ' ') )::int from pg_partitioned_table
where partrelid = t1.attrelid )
;
raise notice ' "partition_col": "%",' ,v_partition_key;
raise notice ' "partition_defs" : [';
-- -- パーティション定義情報
i_wk1 := 0;
for r in ( select replace(cast(t.oid::regclass as varchar),p_table_name||'_','') partition_name
, pg_get_expr(t.relpartbound, t.oid) partition_limit
from pg_inherits i
inner join pg_class t
on t.oid = i.inhrelid
where i.inhparent in (select oid
from pg_class
where relname = p_table_name
and relnamespace = p_schema_name::regnamespace
)
order by t.oid) loop
i_wk1 = i_wk1+1;
if i_wk1 != i_partition_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if v_partition_type = 'range' then
v_wk2 := replace(regexp_replace(r.partition_limit,'FOR.*TO \(',''),')','');
raise notice ' { "partition_name": "%", "partition_limit": "%" }%' ,r.partition_name ,v_wk2 ,v_wk1;
elsif v_partition_type = 'list' then
v_wk2 := regexp_replace(r.partition_limit,'FOR.*IN ','');
raise notice ' { "partition_name": "%", "partition_limit": "%" }%' ,r.partition_name ,v_wk2 ,v_wk1;
elsif v_partition_type = 'hash' then
raise notice ' { "partition_name": "%" }%' ,r.partition_name ,v_wk1;
else
raise notice 'unsupported partition type found';
end if;
end loop;
raise notice ' ]';
raise notice ' },';
end if;
-- 主キー情報
select count(*) strict into i_primary_count
from information_schema.table_constraints
where table_catalog = 'test'
and table_schema = p_schema_name
and table_name = p_table_name
and constraint_type = 'PRIMARY KEY'
;
if i_primary_count = 0 then
raise notice ' "primary": {},';
else
for r in ( select t2.constraint_name constraint_name
,'"'||replace(replace(substring(t1.indexdef from (position('(' in t1.indexdef) )+1 for (position(')' in t1.indexdef) - position('(' in t1.indexdef)-1) ),' ',''),',','","')||'"' column_name
from pg_indexes t1
inner join information_schema.table_constraints t2
on t1.schemaname = t2.table_schema
and t1.tablename = t2.table_name
and t2.table_catalog = 'test'
and t2.constraint_type = 'PRIMARY KEY'
and t1.indexname = t2.constraint_name
where t1.schemaname = p_schema_name
and t1.tablename = p_table_name ) loop
raise notice ' "primary": { "constraint_name": "%", "index_cols": [%] },' ,r.constraint_name, r.column_name;
end loop;
end if;
-- インデックス情報
select count(*) strict into i_index_count
from pg_indexes t1
where t1.schemaname = p_schema_name
and t1.tablename = p_table_name
and not exists (
select 1 from information_schema.table_constraints
where table_catalog = 'test'
and table_schema = t1.schemaname
and table_name = t1.tablename
and constraint_name = t1.indexname
and constraint_type = 'PRIMARY KEY'
)
;
if i_index_count = 0 then
raise notice ' "indexes": []';
else
raise notice ' "indexes": [';
i_wk1:= 0;
for r in ( select t1.indexname
,t3.indisunique
,'"'||replace(replace(substring(t1.indexdef from (position('(' in t1.indexdef) )+1 for (position(')' in t1.indexdef) - position('(' in t1.indexdef)-1) ),' ',''),',','","')||'"' column_name
from pg_indexes t1
inner join pg_class t2
on t2.relnamespace = t1.schemaname::regnamespace
and t2.relname = t1.indexname
inner join pg_index t3
on t2.oid = t3.indexrelid
where t1.schemaname = p_schema_name
and t1.tablename = p_table_name
and not exists (
select 1 from information_schema.table_constraints
where table_catalog = 'test'
and table_schema = t1.schemaname
and table_name = t1.tablename
and constraint_name = t1.indexname
and constraint_type = 'PRIMARY KEY'
)
order by t2.oid ) loop
i_wk1 := i_wk1+1;
if i_wk1 != i_index_count then
v_wk1:= ',';
else
v_wk1:= '';
end if;
if r.indisunique is true then
v_wk2:= 'true';
else
v_wk2:= 'false';
end if;
raise notice ' { "index_name": "%", "index_cols": [%] ,"unique": "%"}%' ,r.indexname, r.column_name, v_wk2, v_wk1;
end loop;
raise notice ' ]';
end if;
raise notice '}';
end;
$$;
call ddl2json();
call ddl2json('public','tab1');
call ddl2json('public','tab2');
call ddl2json('public','tab3');
call ddl2json('public','tab4');
psql test <<EOF 2> tab1.json
call ddl2json('public','tab1');
EOF
sed -i 's/^NOTICE: //' tab1.json
- SQL Server
(2022)
drop procedure ddl2json;
go
create or alter procedure ddl2json(
@p_schema_name varchar(4000) = 'dbo'
,@p_table_name varchar(4000) = 'tab1'
)
as
begin
set nocount on;
declare @v_comments varchar(4000);
declare @v_partition_type varchar(4000);
declare @v_partition_key varchar(4000);
declare @i_col_count integer;
declare @i_partition_count integer;
declare @i_primary_count integer;
declare @i_index_count integer;
declare @v_wk1 varchar(4000);
declare @v_wk2 varchar(4000);
declare @v_wk3 varchar(4000);
declare @v_wk4 varchar(4000);
declare @v_wk5 varchar(4000);
declare @v_wk6 varchar(4000);
declare @v_wk7 varchar(4000);
declare @v_wk8 varchar(4000);
declare @i_wk1 bigint;
declare @i_wk2 bigint;
declare @i_wk3 bigint;
declare @i_wk4 bigint;
declare @i_wk5 bigint;
declare @i_wk6 bigint;
declare @i_wk7 bigint;
print '{';
print ' "schema_name": "'+@p_schema_name+'",';
print ' "table_name": "'+@p_table_name+'",';
-- テーブルコメント情報
set @v_comments = ( select cast(t2.value as varchar)
from sys.tables t1
inner join sys.extended_properties t2
on t1.object_id = t2.major_id
where t1.name = @p_table_name
and schema_name(t1.schema_id) = @p_schema_name
and t2.minor_id = 0 );
print ' "table_desc": "'+@v_comments+'",';
-- カラム情報
set @i_col_count = ( select count(*)
from sys.tables t1
inner join sys.columns t2
on t1.object_id = t2.object_id
left join sys.extended_properties t3
on t2.object_id = t3.major_id
and t2.column_id = t3.minor_id
where t1.name = @p_table_name
and schema_name(t1.schema_id) = @p_schema_name );
print ' "cols": [';
declare cur2 cursor for select t2.column_id
, t2.name
, t2.system_type_id
, t2.max_length
, t2.precision
, t2.scale
, t2.is_nullable
, cast(t3.value as varchar)
from sys.tables t1
inner join sys.columns t2
on t1.object_id = t2.object_id
left join sys.extended_properties t3
on t2.object_id = t3.major_id
and t2.column_id = t3.minor_id
where t1.name = @p_table_name
and schema_name(t1.schema_id) = @p_schema_name
order by t2.column_id
;
set @i_wk1 = 0
open cur2;
fetch next from cur2 into @i_wk2, @v_wk1, @i_wk3, @i_wk4, @i_wk5, @i_wk6, @i_wk7, @v_wk2;
while @@fetch_status = 0
begin
set @i_wk1 = @i_wk1 + 1;
if @i_wk1 != @i_col_count
set @v_wk5 = ',';
else
set @v_wk5 = '';
if @i_wk7 = 0
set @v_wk6 = 'true';
else
set @v_wk6 = 'false';
-- int-> 56 bigint-> 127 numeric-> 108 decimal-> 106
-- char-> 175 varchar-> 167 nchar-> 239 nvarchar-> 231
-- date-> 40 datetime2-> 42
set @v_wk8 = ( case
when @i_wk3 = 56 then 'int'
when @i_wk3 = 127 then 'bigint'
when @i_wk3 = 108 then 'numeric('+cast(@i_wk5 as varchar)+','+cast(@i_wk6 as varchar)+')'
when @i_wk3 = 106 then 'decimal('+cast(@i_wk5 as varchar)+','+cast(@i_wk6 as varchar)+')'
when @i_wk3 = 175 then 'char('+cast(@i_wk4 as varchar)+')'
when @i_wk3 = 167 then 'varchar('+cast(@i_wk4 as varchar)+')'
when @i_wk3 = 239 then 'nchar('+cast(@i_wk4 as varchar)+')'
when @i_wk3 = 231 then 'nvarchar('+cast(@i_wk4 as varchar)+')'
when @i_wk3 = 40 then 'date'
when @i_wk3 = 42 then 'datetime2'
else 'unsupported data type found'
end );
print ' { "col_name": "'+@v_wk1+'", "col_type": "'+@v_wk8+'", "not_null": "'+@v_wk6+'", "col_desc": "'+@v_wk2+'" }'+@v_wk5;
fetch next from cur2 into @i_wk2, @v_wk1, @i_wk3, @i_wk4, @i_wk5, @i_wk6, @i_wk7, @v_wk2;
end
close cur2;
deallocate cur2;
print ' ],';
-- パーティション情報
set @i_partition_count = ( select count(*)
from sys.indexes i
inner join sys.partition_schemes ps on ps.data_space_id = i.data_space_id
inner join sys.partition_functions pf on pf.function_id = ps.function_id
inner join sys.partition_range_values rv on pf.function_id = rv.function_id
where i.object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and i.index_id in (0,1) );
if @i_partition_count = 0
print ' "partition": {},';
else
begin
-- パーティションタイプとパーティションキー取得
print ' "partition": {';
print ' "partition_type": "range",';
set @v_partition_key = ( select c.name
from sys.tables t
inner join sys.indexes i
on t.object_id = i.object_id
and i.type <= 1
inner join sys.partition_schemes ps
on ps.data_space_id = i.data_space_id
inner join sys.index_columns ic
on ic.object_id = i.object_id
and ic.index_id = i.index_id
and ic.partition_ordinal >= 1
inner join sys.columns c
on ic.object_id = c.object_id
and ic.column_id = c.column_id
where t.name = @p_table_name
and schema_name(t.schema_id) = @p_schema_name );
print ' "partition_col": "'+@v_partition_key+'",';
print ' "partition_defs" : [';
-- パーティション定義情報
declare cur3 cursor for select "'"+cast(rv.value as varchar)+"'"
from sys.indexes i
inner join sys.partition_schemes ps on ps.data_space_id = i.data_space_id
inner join sys.partition_functions pf on pf.function_id = ps.function_id
inner join sys.partition_range_values rv on pf.function_id = rv.function_id
where i.object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and i.index_id in (0,1)
order by rv.boundary_id;
set @i_wk1 = 0
open cur3;
fetch next from cur3 into @v_wk1;
while @@fetch_status = 0
begin
set @i_wk1 = @i_wk1 + 1;
if @i_wk1 != @i_partition_count
set @v_wk2 = ',';
else
set @v_wk2 = '';
print ' { "partition_limit": "'+@v_wk1+'" }'+@v_wk2;
fetch next from cur3 into @v_wk1;
end
close cur3;
deallocate cur3;
print ' ]';
print ' },';
end;
-- 主キー情報
set @i_primary_count = ( select count(*)
from sys.indexes
where object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and is_primary_key = 1
and index_id > 0 ) ;
if @i_primary_count = 0
print ' "primary": {},';
else
begin
declare cur4 cursor for select t1.name index_name
, string_agg( col_name(t2.object_id,t2.column_id) ,'","') within group ( order by t2.key_ordinal) index_column
from sys.indexes t1
inner join sys.index_columns t2
on t1.object_id = t2.object_id
and t1.index_id = t2.index_id
where t1.object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and t1.is_primary_key = 1
and t1.index_id > 0
group by t1.name
;
open cur4;
fetch next from cur4 into @v_wk1,@v_wk2;
while @@fetch_status = 0
begin
print ' "primary": { "constraint_name": "'+@v_wk1+'", "index_cols": ["'+@v_wk2+'"] },';
fetch next from cur4 into @v_wk1,@v_wk2;
end
close cur4;
deallocate cur4;
end;
-- インデックス情報
set @i_index_count = (select count(*)
from sys.indexes t1
where t1.object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and t1.is_primary_key != 1
and t1.index_id > 0
);
if @i_index_count = 0
print ' "indexes": []';
else
begin
print ' "indexes": [';
declare cur5 cursor for select t1.index_id
, t1.name
, t1.is_unique
, string_agg( col_name(t2.object_id,t2.column_id) ,'","') within group ( order by t2.key_ordinal) index_column
from sys.indexes t1
inner join sys.index_columns t2
on t1.object_id = t2.object_id
and t1.index_id = t2.index_id
where t1.object_id in ( select object_id from sys.tables
where name = @p_table_name
and schema_name(schema_id) = @p_schema_name )
and t1.is_primary_key != 1
and t1.index_id > 0
group by t1.index_id, t1.name, t1.is_unique
order by t1.index_id, t1.name, t1.is_unique
;
set @i_wk1 = 0
open cur5;
fetch next from cur5 into @i_wk2, @v_wk1, @i_wk3, @v_wk2;
while @@fetch_status = 0
begin
set @i_wk1 = @i_wk1 + 1;
if @i_wk1 != @i_index_count
set @v_wk3 = ',';
else
set @v_wk3 = '';
if @i_wk3 = 1
set @v_wk4 = 'true';
else
set @v_wk4 = 'false';
print ' { "index_name": "'+@v_wk1+'", "index_cols": ["'+@v_wk2+'"] ,"unique": "'+@v_wk4+'"}'+@v_wk3;
fetch next from cur5 into @i_wk2, @v_wk1, @i_wk3, @v_wk2;
end
close cur5;
deallocate cur5;
print ' ]';
end;
print '}';
end
go
exec ddl2json;
go
exec ddl2json 'dbo', 'tab1';
go
exec ddl2json 'dbo','tab2';
go
SQLCMDPASSWORD='password' sqlcmd -U sa -S 192.168.137.62 -d test -W <<EOF > tab1.json
exec ddl2json 'dbo', 'tab1';
go
EOF