programing

데이터베이스를 설계할 때 참/거짓 값을 여러 개 저장하는 선호되는 방법은 무엇입니까?

telecom 2023. 8. 18. 20:51
반응형

데이터베이스를 설계할 때 참/거짓 값을 여러 개 저장하는 선호되는 방법은 무엇입니까?

제목에 명시된 것처럼 데이터베이스를 설계할 때 참/거짓 값을 하나의 값(예: "Y/N:" 또는 "0/1")으로 저장하는 여러 열을 가진 테이블을 처리하는 선호되는 방법은 무엇입니까?마찬가지로 서로 다른 데이터베이스(예: Oracle 및 SQL Server) 간에 발생할 수 있는 몇 가지 문제가 열 처리 방식에 영향을 미칠 수 있습니까?

SQL Server, 어있BIT0 할 수 , 있지만 할 수는 없습니다.MIN또는MAX.

Oracle당신은 그냥 사용합니다.NUMBER또는CHAR(1).

MySQL그리고.PostgreSQL모든 으로 모든데이유암형변가로환능으로 변환할 수 .BOOLEAN.

모두 두시템지를 지원합니다.BOOLEAN 사용할 수 있는 입니다.WHERE또는ON절:

SELECT  *
FROM    mytable
WHERE   col1

은 불한것능가에서 합니다.SQL Server그리고.Oracle(당신은 거기에 어떤 종류나 술어가 있어야 합니다.)

MySQL,BOOLEAN는 의동입니다어의 입니다.TINYINT(1).

PostgreSQL(스토리지 측면에서는) 그렇지만 논리적으로는 다른 유형으로 암시적으로 변환할 수 없습니다.

제 경험으로는 'Y'나 'N'보다는 char(1)가 더 좋습니다.0과 1을 사용하는 것은 내가 이미 얼마나 많은 맥주를 마셨는지에 따라 약간 혼란스러울 수 있고 C++ 메인() 기능은 성공 시 0을 반환합니다.ENUM 및 BIT 유형은 가치보다 더 큰 문제입니다.

MySQL을 롭습니다.information_schemaVARCHAR(3)를 사용하여 'YES' 또는 'NO'를 나타냅니다.

예:

information_schema.USER_PRIVILEGES (
  ...
  IS_GRANTABLE VARCHAR(3) NOT NULL DEFAULT ''
) 

부울 데이터 유형 대신 부울 값을 저장하는 다른 데이터 모델을 고려할 수 있으며, 이는 다음과 같은 경우에 특히 적합할 수 있습니다.

  • 예/아니오 열이 많은 경우.
  • 앞으로 예/아니오 열을 더 추가해야 할 경우.
  • yes/no 값이 자주 변경되지 않는 경우.

사용자 권한을 정의하는 것은 위의 일반적인 예일 수 있습니다.다음 표를 고려합니다.

Table "Users":             (user_id, name, surname, country)

Table "Permissions":       (permission_id, permission_text)

Table "Users_Permissions": (user_id, permission_id)

Permissions표 사용자에게 적용 가능한 모든 권한을 정의할 수 있습니다.은 행추야합니다해가에 해야 할 입니다.Permissions각 yes/no 속성에 대한 표입니다.이렇게 하면 데이터베이스 스키마를 수정할 필요 없이 나중에 새 권한을 쉽게 추가할 수 있습니다.

모델을 하면 위모델사면다음할을당여하값을 TRUE다니냅나를 .user_idpermission_id에 시대에Users_Permissions테이블. 그렇지 않으면 기본적으로 FALSE가 됩니다.

예:

Table "Permissions"

permission_id   text
-----------------------------------
1               "Read Questions"
2               "Answer Questions"
3               "Edit Questions"
4               "Close Questions"


Table "Users_Permissions"

user_id         permission_id
-----------------------------------
1               1
1               2
1               3
2               1
2               3

이점

  • 인덱싱: 의 인덱스를 사용하여 특정 사실을 쉽게 쿼리할 수 있습니다.
  • 공간: 잘못된 값이 많은 경우 기본 규칙에 따라 공간이 절약됩니다.
  • 정규화됨:사실은 그들 자신의 표에서 정의됩니다.Permissions그리고.Users_Permissions할 수 .각 사실에 대한 더 많은 정보를 쉽게 저장할 수 있습니다.

단점들

  • 쿼리:단순 쿼리에는 JOIN이 필요합니다.
  • 거짓으로 설정:값을 false로 설정하려면 행을 삭제해야 합니다.Users_Permissions표).그렇지 않으면 다음에서 '삭제됨' 플래그를 사용할 수 있습니다.Users_Permissions테이블 - 권한이 수정된 시간 및 사용자와 같은 감사 추적에 대한 정보를 저장할 수도 있습니다.행을 삭제하면 이 정보를 저장할 수 없습니다.

사용 중인 특정 데이터베이스 엔진에 적합한 모든 것을 사용합니다.데이터베이스를 처리해야 하는 인터페이스입니다.데이터베이스에 대한 코드 측 인터페이스가 충분히 모듈화된 경우, 기본 데이터베이스에서 다른 부울 형식을 처리하는 것은 단순한 한 줄 변경에 불과합니다.

저는 "Y/N" 값이 "1/0" 값보다 더 의미 있다고 생각합니다.Oracle을 사용하면 데이터베이스 엔진에서 최대한 데이터를 검증할 수 있도록 다음 작업을 수행할 수 있습니다.

  • 열을 char(1)로 정의합니다.
  • 가능한 값이 "in"('Y', 'N')으로 제한되는 확인 제약 조건 추가
  • 비즈니스 규칙과 일치하는 경우, 이 규칙을 무효화하지 마십시오. 이렇게 하면 SQL에서 'Y'가 아닌 모든 항목의 값이 'N'이라고 암시적으로 가정할 때 문제를 방지할 수 있습니다.

DBMS가 MySQL과 같은 부울 데이터 유형을 지원하는 경우 이를 사용합니다.Oracle처럼 그렇지 않으면 일반적으로 Y 또는 N 값이 있는 char(1)를 사용합니다.후자의 경우에는 Java, C++ 또는 어떤 부울 형식이든 Y/N에서 Y/N으로 변환하기 위한 몇 가지 함수를 작성하는 것이 좋습니다.이것은 꽤 사소한 함수이지만 Y나 N 이외의 null이나 값과 같은 경우를 처리해야 할 것이고 당신은 그것을 지속적으로 하기를 원합니다.

비트 연산으로 플래그를 단일 변수로 패킹하지 않을 것입니다.예, 이렇게 하면 디스크 공간을 절약할 수 있지만, 가격은 훨씬 더 복잡하고 오류가 발생할 가능성이 높습니다.만약 당신의 DBMS가 비트 연산을 지원하지 않는다면 -- 그리고 저는 그런 일을 해본 적이 없기 때문에, 저는 어떤 일을 하고 싶은지, 만약 있다면 -- 당신은 그런 플래그를 기준으로 선택하거나 정렬하는 데 정말 어려움을 겪을 것입니다.물론, 다른 기준을 충족하는 모든 레코드를 검색한 다음 적절한 플래그 값을 가진 레코드를 호출 코드에서 제거할 수 있습니다.하지만 레코드의 일부만 원하는 플래그 값을 가지고 있고 다른 많은 레코드를 조인하는 쿼리가 있다면 어떻게 될까요?"select employee.name , select employee pay에서 sum(pay.mount)을 사용하여 직원이 가입한 급여의 합계(pay.mount)를 사용합니다.executive=true and pay.sshot=true".where 절을 사용하면 매우 적은 수의 레코드를 검색할 수 있습니다.그렇지 않으면 전체 데이터베이스를 검색할 수 있습니다.

요즘은 디스크 공간이 저렴하기 때문에 디스크 절약은 중요하지 않습니다.만약 여러분이 정말로 엄청난 수의 깃발들을 가지고 있다면 -- 레코드당 수백 또는 수천 개의 깃발들처럼 -- 저는 그것들을 포장하는 경우가 있을 것이라고 생각합니다.하지만 그것은 제가 선택한 디자인 목록보다 훨씬 아래에 있을 것입니다.

편집: "SQL boolean"을 "Java boolean"으로 변환하는 클래스 작성에 대해 자세히 설명하겠습니다.어떤 언어든 마찬가지이지만, 예를 들어 자바를 사용하겠습니다.

DBMS에 부울 형식이 내장되어 있으면 Java를 사용하여 ResultSet.getBoolean()으로 부울 변수로 직접 읽을 수 있습니다.

하지만 만약 여러분이 문자 "Y"나 "N"으로 저장해야 한다면, 여러분은 그것을 문자열로 읽어야 합니다.따라서 다음과 같은 클래스를 선언하는 것이 타당합니다.

class MyBoolean
{
  boolean value;
  final static MyBoolean TRUE=new MyBoolean(true), FALSE=new MyBoolean(false);
  public MyBoolean(boolean b)
  {
    value=b;
  }
  public MyBoolean(String s)
  {
    if (s==null)
      return null;
    else if (s.equals("Y"))
      return MyBoolean.TRUE;
    else
      return MyBoolean.FALSE;
  }
  public static String toString(MyBoolean b)
  {
    if (b==null)
      return null;
    else if (b.value)
      return "Y";
    else
      reutrn "N";
  }
  public String toString()
  {
    return toString(this);
  }
}

그런 다음 "MyBoolean flag=new MyBoolean(rs.getString("flag))"을 사용하여 데이터베이스에서 부울을 쉽게 선택할 수 있습니다."rs.setString("flag", flag.toString();"을 사용하여 데이터베이스에 씁니다.

그리고 물론 다른 부울적인 것들이 필요하다면 필요한 다른 논리를 클래스에 추가할 수 있습니다.어떤 목적으로 부울을 T/F, Yes/No, On/Off 등으로 표시하려면 유사한 코드를 반복적으로 쓰는 대신 String 변형(TFSring 또는 String(값, 참 텍스트, 거짓 텍스트) 또는 기타 항목에 대체 항목을 추가하면 됩니다.

열을 추가하는 대신 다른 테이블을 만드는 것이 좋습니다.끝까지 들어봐요...

이름이 지정된 테이블이 있다고 가정합니다.Customer:

CREATE TABLE Customer
(
  CustomerID NUMBER,
  Name       VARCHAR(100)
)

이제 검색 결과에 고객을 표시할 수 있는지 여부를 지정하려고 합니다.한 가지 옵션은 두 가지 가능한 상태 중 하나를 나타내는 일부 열을 추가하는 것입니다.

CREATE TABLE Customer
(
  CustomerID NUMBER,
  Name       VARCHAR(100),
  Searchable BOOLEAN /* or CHAR(1) or BIT... */
)

검색 쿼리는 다음과 같습니다.

SELECT CustomerID, Name
  FROM Customer
 WHERE Name LIKE '%TheCustomerNameIAmLookingFor%'
   AND Searchable = TRUE /* or 'Y' or 0... */

이것은 멋지고 간단합니다.이 스레드의 많은 사람들은 구문이 다양한 데이터베이스에서 잘 작동하도록 하기 위해 이 열이 어떤 데이터 유형이어야 하는지를 선택하는 데 좋은 조언을 제공합니다.

대안: 별도의 표 작성

는추대신하에 다른 Customer다음을 저장하는 별도의 테이블을 만들 것입니다.CustomerID검색 가능한 모든 고객의.

CREATE TABLE Customer
(
  CustomerID NUMBER,
  Name       VARCHAR(100)
)

CREATE TABLE SearchableCustomer
(
  CustomerID NUMBER
)

의 고객이 검색 가능한 것으로 간주됩니다.CustomerID합니다.SearchableCustomertable.는 다음과 이제 고객 검색을 위한 쿼리는 다음과 같습니다.

SELECT CustomerID, Name
  FROM Customer
 WHERE Name LIKE '%TheCustomerNameIAmLookingFor%'
   AND CustomerID IN (SELECT CustomerID FROM SearchableCustomer)

이 전략은 RDBMS 간에 매우 쉽게 전송됩니다.

  • 찾기는 검색가고다사다용니합음을 합니다.INJOIN
  • 을 검색 한 상태로 만드는 은 다을사검설가정로능을 합니다.INSERT
  • 상태로 만드는 은 고을검만방법을 합니다.DELETE

놀라운 혜택

이 원하는 수 .SearchableCustomer테이블 대신 보기:

CREATE VIEW SearchableCustomer AS
SELECT CustomerID
  FROM Customer
 WHERE Name LIKE 'S%' /* For some reason, management only cares about customers whose name starts with 'S' */

당신의 검색 질의는 전혀 변하지 않습니다! :D 제 경험상, 이것은 엄청난 유연성으로 이어졌습니다.

비트 열은 일반적으로 적어도 SQL Server에서 T/F 또는 Y/N 유형 값을 나타내는 데 사용됩니다.데이터베이스 순수주의자는 비트 열이 "하드웨어에 너무 가깝기 때문에" 데이터베이스에 위치가 없다고 말할 수 있지만, Joe Celko입니다.

"내 테이블에서 선택 * col1

SQL Server 및 Oracle에서는 불가능합니다(어떤 종류의 용어나 술어가 있어야 함)."

이는 Oracle 및 SQL Server가 실제로 얼마나 터무니없고 우스꽝스러운 혐오스러운 존재인지 보여주는 것일 뿐입니다.

col1이 Boolean 유형으로 선언되면 "col1"이라는 표현은 술어입니다.

WHERE 절의 의미론에서 표현식이 true 값으로 평가되어야 하고 일부 열이 true 값 유형으로 선언되면 "WHERE that-column"이 허용되고 지원되어야 합니다.마침표.무능한 평범한 돌팔이를 위해 저자를 폭로하지 않는 모든 시스템.

일반적으로 BIT/BOOL 값을 전혀 사용하지 않고 이 작업을 수행합니다.대신에 저는 세 개의 테이블을 가질 것입니다.우리가 프로젝트 관리 시스템을 가지고 있다고 가정해 보겠습니다. 그리고 이 프로젝트들은 많은 속성을 가지고 있습니다.

그리고 우리는 테이블을 가지고 있습니다.

프로젝트.프로젝트_ID(INT),이름(VARCHAR)
기여하다속성_ID(INT),이름(VARCHAR)
프로젝트 특성_Rel프로젝트_ID(INT),속성_ID(INT)

프로젝트 속성이 참인지 거짓인지는 ProjectAttribute_Rel에 해당하는 줄이 있는지 여부에 따라 달라집니다.

일반적으로 속성_을 처리합니다.코드에 ID가 있으므로 프로젝트의 속성을 읽을 때(프로젝트가 있는 것으로 추정됨)_ID), 다음을 수행합니다(PHP가 임의로 예제로 사용됨).

$arrAttributes = array();
$oQuery = mysql_query('
    SELECT Attribute_ID
    FROM ProjectAttribute_Rel
    WHERE Project_ID = '.addslashes($iProjectId).'
');
while ($rowAttribute = mysql_fetch_assoc($oQuery)) {
    $arrAttributes[] = $rowAttribute['Attribute_ID'];
}

이때 $arrAttributes에 프로젝트 속성이 존재하는지 여부를 확인하여 프로젝트 속성이 참인지 여부를 확인할 수 있습니다.PHP에서 이것은 다음과 같습니다.

if (in_array($arrAttributes, $iAttributeId)) {
    // Project attribute is true!
}

또한 이 접근 방식을 사용하면 업데이트할 때, 삽입할 때(SELECT *가 코드가 나쁘기 때문에) 다시 선택할 때, 너무 많은 속성이 나열되지 않도록 모든 정렬 스턴트를 수행할 수 있습니다.이는 사용 가능한 특성을 찾기 위해 항상 테이블 속성을 반복적으로 검색할 수 있기 때문입니다. 따라서 속성을 추가하고 이런 방식으로 작업을 수행하면 속성을 추가/편집/삭제하는 작업이 거의 없습니다.속성 자체가 코드가 아닌 데이터베이스에 정의되어 있기 때문에 SQL을 변경할 필요가 없을 가능성이 높습니다.

이게 도움이 되길 바랍니다.

언급URL : https://stackoverflow.com/questions/2200063/when-designing-databases-what-is-the-preferred-way-to-store-multiple-true-fal

반응형