2011-01-25 57 views
2

我需要有一些關鍵表一種「版本」,並試圖實現它在一個相當簡單的方法:SQL Server觸發器和sqlalchemy干擾問題。幫助需要

CREATE TABLE [dbo].[Address] (
    [id] bigint IDENTITY(1, 1) NOT NULL, 
    [post_code] bigint NULL, 
... 
) 

CREATE TABLE [dbo].[Address_History] (
    [id] bigint NOT NULL, 
    [id_revision] bigint NOT NULL, 
    [post_code] bigint NULL, 
... 
    CONSTRAINT [PK_Address_History] PRIMARY KEY CLUSTERED ([id], [id_revision]), 
    CONSTRAINT [FK_Address_History_Address]... 
    CONSTRAINT [FK_Address_History_Revision]... 
) 

CREATE TABLE [dbo].[Revision] (
    [id] bigint IDENTITY(1, 1) NOT NULL, 
    [id_revision_operation] bigint NULL, 
    [id_document_info] bigint NULL, 
    [description] varchar(255) COLLATE Cyrillic_General_CI_AS NULL, 
    [date_revision] datetime NULL, 
... 
) 

和一堆關於插入/更新觸發器/刪除每個表,旨在存儲它的變化。

我的應用程序是基於PyQt的+ SQLAlchemy的,當我嘗試插入一個實體,存儲在一個版本表,SQLAlchemy的觸發一個錯誤:

The target table 'Heritage' of the DML statement cannot have 
any enabled triggers if the statement contains 
an OUTPUT clause without INTO clause. 
(334) (SQLExecDirectW); [42000] 
[Microsoft][ODBC SQL Server Driver] 
[SQL Server]Statement(s) could not be prepared. (8180)") 

我該怎麼辦?我必須使用sqlalchemy。 如果可以給我一個建議,我怎麼才能實現沒有觸發器的版本控制,它會很酷。

+0

由於錯誤說,你的SQL語句顯然包含一個`OUTPUT`子句,對吧?你可以把它變成一個`OUTPUT(columns)INTO(表變量)`子句嗎?這應該(希望)解決錯誤提到的問題... – 2011-01-25 10:54:05

+0

sqlalchemy是ORM工具,它使插入sql查詢,更新ot本身刪除實體: – 2011-01-25 13:08:58

+0

不熟悉SQL Alchemy - 有沒有辦法在配置它時「撒謊」它,以便它相信它正在與SQL Server 2000實例交談(而不是更高版本,並且假設您不需要以後的功能) ? SQL Server 2000沒有OUTPUT子句,所以它可能不會生成這樣的SQL。 – 2011-01-26 13:22:11

回答

3

你應該設置「implicit_returning」到「假」,以避免由SQLAlchemy中生成的查詢「輸出」的使用(這應該可以解決您的問題):

class Company(sqla.Model): 
    __bind_key__ = 'dbnamere' 
    __tablename__ = 'tblnamehere' 
    __table_args__ = {'implicit_returning': False} # http://docs.sqlalchemy.org/en/latest/dialects/mssql.html#triggers 
    id = sqla.Column('ncompany_id', sqla.Integer, primary_key=True) 
    ... 
0

這不會直接回答你的問題,但根據我的經驗,使用觸發器會導致無盡的痛苦,因此不惜一切代價避免它們。如果你自己管理所有的數據,那麼簡單的答案是你自己填充版本歷史表。這也意味着你在一個地方擁有所有的商業邏輯,這是一個獎勵!

1

我似乎不能添加評論,所以添加另一個答案。

這並不複雜,我建議它比將您的業務邏輯放在域中而另一半放在數據庫觸發器中不那麼脆弱。

就我個人而言,我會用some_list_of_other_entities歷史列表的引用來編寫我自己的列表對象,並在Remove和Add方法中維護您的歷史記錄。

這樣,即使將對象保存到ORM中,對象也會自動更新。

public class ListOfOtherEntities : System.Collections.IEnumerable 
{ 
    // Add list stuff here... 

    public void Remove(MyEntity obj) 
    { 
     this.List.Remove(obj); 
     this.History.Add(new History("Added a object!"); 
    } 

    public void Remove(MyEntity obj) 
    { 
     this.List.Remove(obj); 
     this.History.Add(new History("Removed a object!"); 
    } 
} 

這樣,你的對象自動是最新的,甚至它們保存到你的ORM和另一名開發人員查看代碼可以看到你很容易做的事情了。