문제

목표는 비즈니스 레코드 삽입, 업데이트 및 삭제와 같은 활동을 저장하는 것입니다.

내가 고려하고있는 한 가지 해결책은 레코드 당 하나의 테이블을 사용하여 추적하는 것입니다. 간단한 예는 다음과 같습니다.

CREATE TABLE ActivityTypes
(
    TypeId              int IDENTITY(1,1)       NOT NULL,
    TypeName            nvarchar(50)            NOT NULL,

    CONSTRAINT PK_ActivityTypes          PRIMARY KEY (TypeId),
    CONSTRAINT UK_ActivityTypes          UNIQUE (TypeName)
)

INSERT INTO ActivityTypes (TypeName) VALUES ('WidgetRotated');
INSERT INTO ActivityTypes (TypeName) VALUES ('WidgetFlipped');
INSERT INTO ActivityTypes (TypeName) VALUES ('DingBatPushed');
INSERT INTO ActivityTypes (TypeName) VALUES ('ButtonAddedToDingBat');

CREATE TABLE Activities
(
    ActivityId          int IDENTITY(1,1)       NOT NULL,
    TypeId              int                     NOT NULL,
    AccountId           int                     NOT NULL,
    TimeStamp           datetime                NOT NULL,

    CONSTRAINT PK_Activities                      PRIMARY KEY (ActivityId),
    CONSTRAINT FK_Activities_ActivityTypes        FOREIGN KEY (TypeId)
                                                  REFERENCES ActivityTypes (TypeId),
    CONSTRAINT FK_Activities_Accounts             FOREIGN KEY (AccountId)
                                                  REFERENCES Accounts (AccountId)
)

CREATE TABLE WidgetActivities
(
    ActivityId          int                     NOT NULL,
    WidgetId            int                     NOT NULL,

    CONSTRAINT PK_WidgetActivities                  PRIMARY KEY (ActivityId),
    CONSTRAINT FK_WidgetActivities_Activities       FOREIGN KEY (ActivityId)
                                                    REFERENCES Activities (ActivityId),
    CONSTRAINT FK_WidgetActivities_Widgets          FOREIGN KEY (WidgetId)
                                                    REFERENCES Widgets (WidgetId)
)

CREATE TABLE DingBatActivities
(
    ActivityId          int                     NOT NULL,
    DingBatId           int                     NOT NULL,
    ButtonId            int,

    CONSTRAINT PK_DingBatActivities                  PRIMARY KEY (ActivityId),
    CONSTRAINT FK_DingBatActivities_Activities       FOREIGN KEY (ActivityId)
                                                     REFERENCES Activities (ActivityId),
    CONSTRAINT FK_DingBatActivities_DingBats         FOREIGN KEY (DingBatId)
                                                     REFERENCES DingBats (DingBatId)
    CONSTRAINT FK_DingBatActivities_Buttons          FOREIGN KEY (ButtonId)
                                                     REFERENCES Buttons (ButtonId)
)

이 솔루션은 위젯 또는 Dingbat 레코드 ID가 주어진 모든 활동을 가져 오는 데 유리한 것처럼 보이지만 모든 활동을 가져온 다음 어떤 레코드를 참조하는지 결정하는 데 그리 좋지는 않습니다.

즉,이 예에서 모든 계정 이름과 타임 스탬프는 별도의 테이블에 저장되므로 사용자에게 중점을 둔 보고서를 쉽게 만들 수 있으며 활동이 무엇인지 알 필요없이 시간 간격에 중점을 둡니다.

그러나 특히 유형별로 활동에 대해보고하고 싶다면이 솔루션은 일반 활동 테이블이 참조하는 활동 유형을 결정해야합니다.

모든 활동 유형을 한 테이블에 넣을 수는 있지만 ID는 외래 키에 의해 제약을받을 수 없으며 대신 테이블 이름이 ID로 사용될 수있어 동적 쿼리를 사용하게됩니다.

예제에서 Dingbatactivity에는 선택적 버튼 ID가 있습니다. 버튼 이름이 Dingbat에 추가 된 후 편집 된 경우, 활동은 버튼을 참조하고 이름을 알 수 있습니다. 따라서 보고서가 Dingbat에 의해 모든 활동을 나열하고 버튼으로 버튼 이름 변경이 변경되면 버튼 이름이 변경됩니다. 활동 설명에 자동으로 반영됩니다.

다른 아이디어를 찾고 프로그래밍 노력, 데이터 무결성, 성능 및보고 유연성 사이의 아이디어가 어떻게 타협하는지를 찾습니다.

도움이 되었습니까?

해결책

내가 일반적 으로이 문제에 대한 해결책을 건축하는 방식은 물체의 상속과 유사합니다. 특정 단체에서 일어나는 "활동"이 있고 해당 활동을 추적하려는 경우 관련된 엔티티는 거의 확실히 공통점이 있습니다. 기본 테이블이 있습니다. 거기에서 기본 테이블에서 하위 테이블을 만들어 해당 하위 유형에 특정한 것을 추적 할 수 있습니다. 예를 들어, 당신은 다음과 같습니다.

CREATE TABLE Objects   -- Bad table name, should be more specific
(
     object_id     INT          NOT NULL,
     name          VARCHAR(20)  NOT NULL,
     CONSTRAINT PK_Application_Objects PRIMARY KEY CLUSTERED (application_id)
)

CREATE TABLE Widgets
(
     object_id     INT           NOT NULL,
     height        DECIMAL(5, 2) NOT NULL,
     width         DECIMAL(5, 2) NOT NULL,
     CONSTRAINT PK_Widgets PRIMARY KEY CLUSTERED (object_id),
     CONSTRAINT FK_Widgets_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id)
)

CREATE TABLE Dingbats
(
     object_id     INT           NOT NULL,
     label         VARCHAR(50)   NOT NULL,
     CONSTRAINT PK_Dingbats PRIMARY KEY CLUSTERED (object_id),
     CONSTRAINT FK_Dingbats_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id)
)

이제 당신의 활동을 위해 :

CREATE TABLE Object_Activities
(
     activity_id     INT          NOT NULL,
     object_id       INT          NOT NULL,
     activity_type   INT          NOT NULL,
     activity_time   DATETIME     NOT NULL,
     account_id      INT          NOT NULL,
     CONSTRAINT PK_Object_Activities PRIMARY KEY CLUSTERED (activity_id),
     CONSTRAINT FK_Object_Activities_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id),
     CONSTRAINT FK_Object_Activities_Activity_Types
     FOREIGN KEY (activity_type) REFERENCES Activity_Types (activity_type),
)

CREATE TABLE Dingbat_Activities
(
     activity_id     INT     NOT NULL,
     button_id       INT     NOT NULL,
     CONSTRAINT PK_Dingbat_Activities PRIMARY KEY CLUSTERED (activity_id),
     CONSTRAINT FK_Dingbat_Activities_Object_Activities
     FOREIGN KEY (activity_id) REFERENCES Object_Activities (activity_id),
     CONSTRAINT FK_Dingbat_Activities_Buttons
     FOREIGN KEY (button_id) REFERENCES Object_Activities (button_id),
)

영향을 미치는 객체의 유형에 대해 기본 활동에 유형 코드를 추가하거나 하위 테이블에서 존재를 찾아서 결정할 수 있습니다.

여기에 있습니다 그러나 경고 : 물체/활동에 실제로 공통점이있는 것이 있는지 확인 하고이 길을 따라 가야합니다. 동일한 테이블에 분리되지 않은 관련 데이터를 저장하고 싶지 않습니다. 예를 들어이 방법을 사용하여 은행 계좌 거래와 천상 이벤트를 모두 보유한 테이블을 만들 수 있지만 좋은 생각은 아닙니다. 기본 수준에서는 공통점이 있어야합니다.

또한 귀하의 모든 활동이 계정과 관련이 있다고 가정했기 때문에 기본 테이블에 있습니다. 모든 활동과 공통점은 기본 테이블에 있습니다. 하위 유형에만 관련된 것들이 해당 테이블에 들어갑니다. 당신은 심지어 깊은 수준으로 갈 수도 있지만, 옮겨지지 않습니다. 객체도 마찬가지입니다 (다시 한 번 나쁜 이름이지만 실제로 무엇을 다루고 있는지 잘 모르겠습니다). 모든 객체에 색상이 있으면 객체 테이블에 넣을 수 있습니다. 그렇지 않다면 하위 테이블로 들어갑니다.

다른 팁

나는 사지로 나가서 당신이 실제로 성취하려는 것에 대해 몇 가지 거친 추측을 할 것입니다.

당신은 당신이 '상점 활동'을 추적하려고한다고 말합니다. 나는 당신에게 다음과 같은 활동을 가지고 있다고 가정 할 것입니다 : 새 항목 판매 품목 판매 항목 쓰기 품목 고용 직원 임금 직원 업데이트 직원 기록

자, 이러한 활동에는 몇 가지 다른 테이블이 필요합니다. 하나는 인벤토리 용, 부서 용 및 직원 용입니다.

인벤토리 테이블에는 다음과 같은 정보가있을 수 있습니다.

inventory:
  item_id (pk)
  description (varchar)
  number_in_stock (number)
  cost_wholesale (number)
  retail_price (number)
  dept_id (fk)

department:
  dept_id (pk)
  description (varchar)

employee
  emp_id (pk)
  first_name (varchar)
  last_name (varchar)
  salary (number)
  hire_date (date)
  fire_date (date)

따라서 새 항목을 구매할 때는 인벤토리 테이블에서 Number_In_Stock을 업데이트하거나 이전에 없었던 항목 인 경우 새 행을 만듭니다. 항목을 판매 할 때 해당 항목에 대한 숫자 _in_stock (항목을 작성할 때)을 줄입니다.

신입 사원을 고용하면 직원 테이블에 레코드를 추가합니다. 당신이 그들에게 지불하면, 당신은 급여 칼럼에서 그들의 급여를 얻습니다. 당신이 그들을 해고 할 때, 당신은 그들의 기록을 위해 그 칼럼을 채 웁니다 (그리고 지불을 중단하십시오).


이 모든 것에서, 행위 데이터베이스에 의해 수행되지 않습니다. SQL은 정보를 추적하는 데 사용해야합니다. 이러한 업데이트를위한 절차를 작성하는 것이 좋습니다 (송장 기록에서 모든 항목을 업데이트하는 새로운 송장 절차). 그러나 당신은 테이블이 필요하지 않습니다 하다 물건. 사실, 테이블은 할 수 없습니다 하다 아무것.

데이터베이스를 설계 할 때 질문해야 할 질문은 "무엇을해야합니까?"가 아닙니다. "어떤 정보를 추적해야합니까?"

질문에 대한 다른 해석에 근거한 새로운 답변.

무슨 일이 있었는지 목록을 유지하려고합니까? 과거 이벤트의 주문 목록이 필요한 경우 1 개의 테이블 만 있으면됩니다.

action_list
  action_list_id (pk)
  action_desc (varchar)

event_log:
  event_log_id (pk)
  event_time (timestamp)
  action_list_id (fk)
  new_action_added (fk)
  action_details_or_description (varchar)

이것에서 action_list는 다음과 같습니다.

1   'WidgetRotated'
2   'WidgetFlipped'
3   'DingBatPushed'
4   'AddNewAction'
5   'DeleteExistingAction'

event_log는 어떤 활동이 일어 났는지, 언제. 귀하의 조치 중 하나는 "새로운 작업 추가"이며, 'New_Action_Added'열이 이벤트 테이블에 채워야 할 때마다 채취 한 조치는 "새로운 작업 추가"입니다.

업데이트, 제거, 추가 등을위한 작업을 만들 수 있습니다.

편집 : action_details_or_description 열을 이벤트에 추가했습니다. 이런 식으로 행동에 대한 추가 정보를 제공 할 수 있습니다. 예를 들어, "제품 변경 색상 변경"작업이 있으면 새로운 색상의 설명이 "빨간색"일 수 있습니다.

더 광범위하게, 당신은 미리 취할 모든 다양한 유형의 동작을 생각하고 매핑하고 싶을 것이므로 원하는 데이터를 정확하게 포함 할 수있는 방식으로 테이블을 설정할 수 있습니다. 그들에게 넣습니다.

SQL 로그는 어떻습니까?

마지막으로 데이터베이스 트랜잭션 로거가 필요했을 때 대신에 데이터베이스를 트리거하여 레코드를 업데이트하는 대신 데이터베이스가 로그 테이블에 새 레코드를 삽입합니다. 이 기술은 데이터베이스의 각 테이블에 대한 로그를 고정하기 위해 추가 테이블이 필요했으며 로그 테이블에는 타임 스탬프가있는 추가 열이있었습니다. 이 기술을 사용하면 원하는 경우 레코드의 사전 및 사후 업데이트 상태를 저장할 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top