0

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

我尝试的另一种可能性是使用 MS SQL Server 导入数据向导。这当然是隐藏的 SSIS,它需要 32 位 ODBC 驱动程序。这得到了一部分,但它无法尝试创建目标表,因为它不了解 CLOB 数据类型是什么。

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

关于我可以使用哪些工具来做到这一点的任何想法?

谢谢。

4

2 回答 2

1

唉,4D ODBC 驱动程序是一个(咳咳)容器,里面装满了如此强大的肥料,以至于没有人可以忍受它的气味......

没有简单的答案,但如果你在这里做到了,那么你已经处于一个糟糕的地方,所以我将分享一些有帮助的东西。

您可以使用免费的ODBC 查询工具,该工具可以通过 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 导出的数据直接加载到数据库中。所以我完成了。

祝你好运。

于 2018-07-26T22:54:42.203 回答
0

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

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

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

最好的办法是联系开发人员并寻求帮助。如果这不是一个选项,让事情运行起来。如果它真的很旧,您可以联系 4D 获取存档版本的副本。根据它是哪个版本以及它的构建方式(编译、解释、引擎),您的选择会有所不同。

[编辑] 开发人员可以指定通过 SQL 可用的模式,并且出于安全或可用性原因,我们经常限制公开的内容。听起来这里可能就是这种情况——它可以解释为什么你看不到整个结构。

这也可以通过原生 4D 结构来完成。我可以逐个字段/逐个表地限制在用户模式下可以看到多少 4D 结构。通常这是为了减少系统对用户的困惑,但这也是一种强制数据安全的方法。因此,我可以允许您下载所有“数据”,同时不允许您下载使数据库正常工作的内部元素。

如果您能够导出您想要的数据,即使速度很慢,这听起来也像是要做的事情。

于 2018-07-20T16:32:59.767 回答