从4D数据库生成DDL

时间:2018-07-19 07:42:58

标签: ssis odbc 4d-database

我继承了一个4D数据库,我需要从中提取所有数据以导入到另一个关系数据库中。 4D数据库ODBC驱动程序似乎有很多奇怪之处,使它无法用作SQL Server链接服务器。如果有人需要,但我可以说的话,我可以提供血腥细节。看起来不太可能。

我尝试过的另一种可能性是使用MS SQL Server导入数据向导。当然,这是SSIS的本质,它需要32位ODBC驱动程序。这是其中的一部分,但是由于无法理解什么是CLOB数据类型,因此无法创建目标表。

所以我的理由是,如果我可以从4D数据库中的现有表结构中构建DDL,那么如果我先创建表,就可以使用数据导入向导来导入数据。

关于我可以使用哪些工具进行此操作的任何想法?

谢谢。

2 个答案:

答案 0 :(得分:0)

Boffin, “继承4D数据库”是否意味着它正在运行,或者您具有数据文件和结构但无法打开它?

如果它正在运行并且您可以访问用户环境,那么要做的一件简单的事情就是使用4D的导出功能。如果您无权访问用户环境,则ODBC的唯一选择就是设计为允许ODBC或开发人员提供了某些导出功能。

如果无法运行它,则将无法直接访问数据文件。 4D使用专有的数据结构,并且版本之间发生了变化。默认情况下,它没有加密,因此您实际上可以读取/提取数据,但不能仅构建DDL并从中提取数据。 ODBC是正在运行的应用程序与某些其他源之间的连接。

您最好的选择是与开发人员联系并寻求帮助。如果那不是一个选择,那就让它开始运行。如果确实很旧,可以联系4D以获取存档版本的副本。根据版本和版本(编译,解释,引擎化)的不同,选项也有所不同。

[编辑]开发人员可以指定可通过SQL使用的架构,出于安全性或可用性的原因,我们经常限制公开的架构。听起来这里可能是这种情况-它可以解释为什么看不到总体结构。

这也可以使用本机4D结构完成。我可以限制在用户模式下逐个字段/逐个表地显示4D结构的数量。通常,这是为了减少系统对用户的混乱,但这也是一种增强数据安全性的方法。因此,我可以允许您下载所有“数据”,而不允许您下载使数据库正常工作的内部元素。

如果能够导出数据,即使速度很慢,听起来也很像。

答案 1 :(得分:0)

可惜,4D ODBC驱动程序是一艘(肥料)船,里面装满了强大的肥料,以至于没人能忍受它的气味...

没有简单的答案,但是,如果您在这里取得成功,那么您已经处在一个糟糕的境地,因此我将分享一些对您有帮助的事情。

您可以使用免费软件ODBC Query Tool,该软件可以使用64位驱动程序通过用户或系统DSN连接到ODBC。然后运行此查询:

SELECT table_id, table_name,column_name, data_type, data_length, nullable, column_id FROM _user_columns ORDER BY table_id, column_id limit ALL

注意:默认情况下,ODBC查询工具将获取前200行的页面。您需要滚动到结果集的底部。

我还尝试了JetBrains和RazorSQL的DataGrip。都不适合4D ODBC DSN。

现在您已经有了这个结果集,将其导出到Excel并保存电子表格。我发现文本文件输出没有用。它们将导出为可读文本,而不是CSV或制表符分隔的

然后,我使用Microsoft SQL Server导入数据向导(它是SSIS)将数据导入到可以操纵的表中。我的目标是SQL Server,因此执行此步骤对我来说很有意义,但是如果您导入到另一个目标数据库,则可以从数据中创建表定义,现在可以使用任何您认为最好的工具。

一旦在表中保存了此内容,便使用该T-SQL脚本生成DDL:

    use scratch;

-- Reference for data types: https://github.com/PhenX/4d-dumper/blob/master/dump.php

declare @TableName varchar(255) = '';

declare C1 CURSOR for 
    select distinct table_name
    from 
        [dbo].[4DMetadata]
    order by 1;

open C1;
fetch next from C1 into @TableName;

declare @SQL nvarchar(max) = '';
declare @ColumnDefinition nvarchar(max) = '';

declare @Results table(columnDefinition nvarchar(max));

while @@FETCH_STATUS = 0
begin
    set @SQL = 'CREATE TABLE [' + @TableName + '] (';
    declare C2 CURSOR for
        select
            '[' + 
            column_name +
            '] ' +
            case data_type
                when 1 then 'BIT'
                when 3 then 'INT'
                when 4 then 'BIGINT'
                when 5 then 'BIGINT'
                when 6 then 'REAL'
                when 7 then 'FLOAT'
                when 8 then 'DATE'
                when 9 then 'DATETIME'
                when 10 then 
                    case 
                        when data_length > 0 then 'NVARCHAR(' + cast(data_length / 2 as nvarchar(5)) + ')'
                        else 'NVARCHAR(MAX)'
                    end
                when 12 then 'VARBINARY(MAX)'
                when 13 then 'NVARCHAR(50)'
                when 14 then 'VARBINARY(MAX)'
                when 18 then 'VARBINARY(MAX)'
                else 'BLURFL' -- Put some garbage to prevent this from creating a table!
            end +
            case nullable
                when 0 then ' NOT NULL'
                when 1 then ' NULL'
            end +
           ', '
        from
            [dbo].[4DMetadata]
        where 
            table_name = @TableName
        order by column_id;
    open C2;
    fetch next from C2 into @ColumnDefinition;

    while @@FETCH_STATUS = 0
    begin
        set @SQL = @SQL + @ColumnDefinition;

        fetch next from C2 into @ColumnDefinition;
    end
    -- Set the last comma to be a closing parenthesis and statement terminating semi-colon
    set @SQL = SUBSTRING(@SQL, 1, LEN(@SQL) - 1) + ');';

    close C2;
    deallocate C2;

    -- Add the result
    insert into @Results (columnDefinition) values (@SQL);
    fetch next from C1 into @TableName;
end
close C1;
deallocate C1;

select * from @Results;

我使用生成的DDL创建数据库表定义。

不幸的是,SSIS无法与4D数据库ODBC驱动程序一起使用。它不断抛出认证错误。但是,您也许可以使用自己的定制工具来加载此数据库,该工具可与4D的ODBC怪异一起使用。

我有我自己的工具(很遗憾,我无法共享它),该工具将XML导出的数据直接加载到数据库中。这样我就结束了。

祝你好运。