触发MSSQL - 输出到文件(XML)

时间:2016-12-16 13:42:37

标签: sql-server xml sql-server-2012

我们有一个非常古老的ERP系统,得到了很好的支持。

现在仓库想要为我们的商品购买新的“商店系统”。这是一个全自动商店系统,需要我们ERP系统的数据。您的ERP系统的支持无法帮助我们,因此我们必须构建自己的解决方案。

我们的想法是将新存储系统的项目“移动”到一个名为(SHUT1)的特殊存储位置,并将“部件号”和“数量”输出到一个文件(xml),该文件可由新的读取软件

我们无法更改ERP系统软件中的任何内容,因此我们必须在SQL Server本身上进行更改。 (我知道,触发器不是“最好”的事情,但我别无选择)

CREATE TRIGGER tr_LagerShut ON dbo.Lagerverwaltung
AFTER INSERT
AS
BEGIN
  IF (SELECT [Lagerort] from Inserted) = 'SHUT1'
  BEGIN
    DECLARE @Cmd VARCHAR(2000) ;
    DECLARE @FormatDate4File VARCHAR(200);

    SET @FormatDate4File = (SELECT(SYSUTCDATETIME()));
    SET @FormatDate4File = (SELECT REPLACE(@FormatDate4File,' ','-'));
    SET @FormatDate4File = (SELECT REPLACE(@FormatDate4File,':','-'));
    SET @FormatDate4File = (SELECT REPLACE(@FormatDate4File,'.','-'));

    SET @Cmd = ( SELECT [Artikelnummer],[Menge] FROM inserted FOR XML PATH('')) ;

    SET @Cmd = 'Echo "' + @Cmd + '" >>"C:\Temp\' + @FormatDate4File +'.xml"' ;

    EXEC xp_cmdshell @Cmd ;
  END;
END;

触发器“安装”很好,但是如果我将存储位置更改为新位置,则ERP系统会以“错误”停止(没有错误描述:(

如果我放下触发器,系统再次正常运行。所以我认为触发器中存在错误,但我找不到它。

有人可以帮忙吗?

阿莱克斯。

2 个答案:

答案 0 :(得分:0)

不知道 ERP系统停止了什么" ERROR" 看起来像...... Frozend GUI?超时?只是没有创建文件?

我的神奇玻璃灯泡告诉我以下内容:您一次插入多行。如果是这样,此语句将中断,因为这样的比较仅对标量值有效。如果inserted中有多行,则无效:

IF (SELECT [Lagerort] from Inserted) = 'SHUT1'.

您的触发器可以简化,但我怀疑,您会喜欢这个结果。使用特殊字符(例如üöä)进行检查并检查是否附上" - 字符......

CREATE TRIGGER tr_LagerShut ON dbo.Lagerverwaltung
AFTER INSERT
AS

BEGIN
    IF EXISTS(SELECT 1 FROM inserted WHERE [Lagerort]='SHUT1')
    BEGIN
        DECLARE @FileName VARCHAR(255) =REPLACE(REPLACE(REPLACE(SYSUTCDATETIME(),' ','-'),':','-'),'.','-');
        DECLARE @Content XML=
        ( 
            SELECT [Artikelnummer],[Menge] FROM inserted WHERE [Lagerort]='SHUT1' FOR XML AUTO,ELEMENTS
        );

        DECLARE @Cmd VARCHAR(4000) = 'Echo "' + CAST(@Content AS VARCHAR(MAX)) + '" >>"c:\temp\' + @FileName + '.xml"' ;
        PRINT @cmd;
        EXEC xp_cmdshell @Cmd ; 
    END
END;

最好用BCP完成。

更新您的评论......

首先,你应该检查一下,如果这种方法有效:

    DECLARE @FileName VARCHAR(255) =REPLACE(REPLACE(REPLACE(SYSUTCDATETIME(),' ','-'),':','-'),'.','-');
    DECLARE @Content XML=
    ( 
        SELECT TOP 5 * FROM sys.objects FOR XML AUTO,ELEMENTS
    );

    DECLARE @Cmd VARCHAR(4000) = 'Echo "' + CAST(@Content AS VARCHAR(MAX)) + '" >>"c:\temp\' + @FileName + '.xml"' ;
    PRINT @cmd;
    EXEC xp_cmdshell @Cmd ; 

如果在c:\temp\中找不到文件:您是否知道,SQL-Server将始终在其自己的上下文中编写?可能是,您正在等待本地c-drive中的文件,但该文件将被实际写入服务器的机器。

如果这是孤立的,它也应该在触发器内工作。您可以将呼叫打包到BEGIN TRY ... END TRY并添加适当的CATCH阻止。

答案 1 :(得分:0)

好吧,“简单”触发器可能真的是一个问题。现在我有了这个想法: (另外一个信息:当插入新行时,时间戳未插入表“Lagerverwaltung”)

伪代码:

Trigger on Table "Lagerverwaltung"
Check if the storage place(s) is "SHUT1"
If "yes"
DECLARE @FileName VARCHAR(255) =REPLACE(REPLACE(REPLACE(SYSUTCDATETIME(),' ','-'),':','-'),'.','-');
create a new table with name dbo + '.' + @filename
Insert all the data (inserted) + row(SYSUTCDATETIME()) AS TimeStamp where 'Lagerort' = 'SHUT1' into new table named 'dbo.' + @filename
DECLARE @Cmd varchar(4000) =  'bcp "select [Artikelnummer],[Menge],[TimeStamp] FROM [wwsbautest].[dbo].@filename WHERE [Lagerort]=''SHUT1'' AND [Menge] > ''0'' FOR XML AUTO, ELEMENTS" queryout "C:\temp\' +  @FileName + '.xml" -c -T';
EXEC xp_cmdshell @Cmd; 
Drop table dbo.@filename;

可能像那样的工作吗?