3

MSSQL で行われた変更をリモートの MySQL データベースと同期する必要があります。同期する変更は、請求書とユーザーをシステムに追加することです。リモート サーバーは常にアクセスできるとは限らないため、MSSQL で行われた変更を保存するための一種のログ テーブルを設定しようとしています。

そのための完全に機能するトリガーを次に示します。

CREATE TRIGGER [dbo].[dokument_insert]
   ON [dbo].[dokument]
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    INSERT INTO [bcg_ekodu].[dbo].[sync_stack] (event,sql, table_name, import_priority)
        SELECT 
            'INSERT',
            'INSERT INTO bills SET
                date = "'+CONVERT(VARCHAR(19),dok_kuup,120)+'", 
                total = "'+CAST(kokkusum AS nvarchar)+'",
                number = "'+RTRIM(dok_nr)+'", 
                created = "'+CONVERT(VARCHAR(19),savetime,120)+'", 
                rounded = "'+CAST(ymardus AS nvarchar)+'",
                currency = "'+CAST(valuuta AS nvarchar)+'", 
                due_date = "'+CONVERT(VARCHAR(19),tasupaev,120)+'", 
                pk_joosep = "'+CAST(dok_kood AS nvarchar)+'",
                joosep_hankija = "'+CAST(hankija AS nvarchar)+'";
             UPDATE
                bills, users, companies 
             SET 
                bills.user_id = users.id,
                bills.imported = NOW()
             WHERE
                bills.imported IS NULL
                AND companies.id = users.company_id
                AND companies.pk_joosep = 10
                AND bills.user_id = users.pk_joosep',
            'bills',
            '200'
        FROM inserted
END

行が「ドキュメント」テーブルに挿入されるたびに、「sync_stack」テーブルに行が挿入されます。「sql」列には、別の (MySQL) データベースに同じ種類の行を作成するための SQL が含まれます。

しかし、このトリガーは機能していません:

CREATE TRIGGER [dbo].[klient_insert]
   ON [dbo].[klient]
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    INSERT INTO [bcg_ekodu].[dbo].[sync_stack] (event,sql, table_name, import_priority)
        SELECT 
            'INSERT',
            'INSERT INTO users SET
                username =10'+CAST(kl_kood as nvarchar)+',
                password = NULL,
                name ="'+LTRIM(RTRIM(kl_nimi))+'",  
                email ="'+CAST(LTRIM(RTRIM(kl_email)) as nvarchar)+'",  
                reference_no ="'+CAST(LTRIM(RTRIM(kl_viide)) as nvarchar)+'",   
                phone ="'+CAST(LTRIM(RTRIM(kl_tel1)) as nvarchar)+'",   
                logins ="'+CAST(0 as nvarchar)+'",  
                last_login = NULL,  
                created ="'+CONVERT(VARCHAR(19),savetime,120)+'",   
                updated = NULL, 
                deleted ="0",   
                address ="'+CAST(LTRIM(RTRIM(kl_aadr1)) as nvarchar)+'",    
                pk_joosep ="'+CAST(kl_kood as nvarchar)+'"',
            'users',
            '210'
        FROM inserted
END

そのトリガーを作成するための上記の SQL の実行は正常に完了しますが、「トリガーされた」テーブルにいくつかの行を挿入しようとすると、次のエラーが発生します。

No row was updated.

The data in row 175 was not committed.
Error Source: .Net SqlClient Data Provider.
Error Message: Cannot insert the value NULL into column 'sql', table 'mydb.dbo.sync_stack'; column does not allow nulls. INSERT fails.

The statement has been terminated.

Correct the errors and retry or press ESC to cancel the change(s).
  • このトリガーを削除すると、このエラーは発生しません。
  • 「sql」列にプレーンテキストだけを挿入すると、期待どおりに機能します。
  • 挿入された行のフィールドを使用すると、テキスト フィールドであっても、再び失敗します。
  • 「sql」列に NULL 値を許可すると、行の挿入は成功しますが、「sql」列に NULL 値が返されます。

2 番目のトリガーも期待どおりに機能させるにはどうすればよいですか?

4

2 に答える 2

8

SQLステートメントに連結しているinsertされた値の少なくとも1つはNULL. COALESCEたとえば、を使用してこれを回避できます。

username =10'+COALESCE(CAST(kl_kood as nvarchar), '')+',

もちろんnvarchar、長さを指定せずに宣言するべきではありませんよね?

于 2012-04-17T21:52:26.107 に答える
-1

任意の値を NULL に連結すると NULL になります。

select 'test' + NULL

結果は null になります。列には次のようなものを使用する必要があります。

select isnull(column, '')

これにより、空の文字列が生成されます。

于 2012-04-17T21:50:24.980 に答える