[sql] 데이터베이스 테이블의 열에 목록을 저장하는 방법

따라서, 당 관련 질문에 대한 메흐 다드의 대답 , 나는 그것을 얻을 에 “적절한”데이터베이스 테이블의 열 목록을 저장하지 않습니다. 오히려 상기 목록의 요소를 효과적으로 보유하는 다른 테이블을 만든 다음 직접 또는 접합 테이블을 통해 연결해야합니다. 그러나 내가 만들고 싶은 목록의 유형은 (연결된 질문의 과일 과 달리) 고유 한 항목으로 구성됩니다.예). 또한 내 목록의 항목은 명시 적으로 정렬되어 있습니다. 즉, 다른 테이블에 요소를 저장하면 액세스 할 때마다 항목을 정렬해야합니다. 마지막으로, 목록은 기본적으로 원자 적입니다. 목록에 액세스하고 싶을 때마다 목록의 일부가 아닌 전체 목록에 액세스하고 싶을 것입니다. 따라서 데이터베이스 쿼리를 실행하여 일부 목록.

AKX의 솔루션 (위에 링크 됨)은 목록을 직렬화하고 이진 열에 저장하는 것입니다. 그러나 이것은 직렬화와 역 직렬화에 대해 걱정해야한다는 것을 의미하기 때문에 불편한 것 같습니다.

더 나은 해결책이 있습니까? 경우가 없다 더 나은 솔루션은 왜? 이 문제는 때때로 발생해야하는 것 같습니다.

… 내가 어디에서 왔는지 알려주는 약간의 추가 정보입니다. 일반적으로 SQL과 데이터베이스를 이해하기 시작하자마자 LINQ to SQL을 사용하게되었으므로 이제는 개체가 어떻게 작동하는지 생각할 필요없이 프로그래밍 개체 모델을 처리 할 것으로 예상하기 때문에 약간 버릇이 생겼습니다. 쿼리되거나 데이터베이스에 저장됩니다.

모두 감사합니다!

남자

업데이트 : 그래서 제가받은 첫 번째 답변에서 “CSV / XML 경로로 갈 수 있지만 …하지 마십시오!”라는 메시지가 표시됩니다. 이제 이유에 대한 설명을 찾고 있습니다. 몇 가지 좋은 참조를 알려주십시오.

또한 내가하고있는 일에 대한 더 나은 아이디어를 제공하기 위해 : 데이터베이스에 (x, y) 쌍의 목록이있는 Function 테이블이 있습니다. (이 표에는 토론에 중요하지 않은 다른 정보도 있습니다.) (x, y) 쌍 목록의 일부를 볼 필요가 없습니다. 오히려 나는 그것들을 모두 가져 와서 화면에 플롯 할 것입니다. 사용자가 노드를 드래그하여 가끔 값을 변경하거나 플롯에 더 많은 값을 추가 할 수 있습니다.



답변

아니요, 단일 열에 일련의 항목을 저장하는 “더 나은”방법은 없습니다. 관계형 데이터베이스는 행 / 열 조합 당 하나의 값을 저장 하도록 특별히 설계되었습니다 . 둘 이상의 값을 저장 하려면 목록을 저장을 위해 단일 값으로 직렬화 한 다음 검색시 역 직렬화해야합니다. 당신이 말하는 것을 할 수있는 다른 방법은 없습니다 (당신이 말하는 것은 일반적으로 절대로하지 말아야 하는 나쁜 생각 이기 때문입니다 ).

그 목록을 저장하기 위해 다른 테이블을 만드는 것이 어리석은 일이라고 생각하지만 이것이 관계형 데이터베이스가하는 일입니다. 당신은 힘겨운 싸움을 벌이고 있으며 특별한 이유없이 관계형 데이터베이스 설계의 가장 기본적인 원칙 중 하나를 위반하고 있습니다. 방금 SQL을 배우고 있다고 말씀 하셨으므로이 아이디어를 피하고 숙련 된 SQL 개발자가 권장하는 방법 을 따르도록 강력히 권합니다.

위반하는 원칙을 데이터베이스 정규화의 첫 번째 단계 인 첫 번째 정규형 이라고 합니다.

지나치게 단순화 할 위험이있는 데이터베이스 정규화는 데이터 무엇인지를 기반으로 데이터베이스를 정의하는 프로세스 이므로 이에 대해 합리적이고 일관된 쿼리를 작성하고 쉽게 유지 관리 할 수 ​​있습니다. 정규화는 데이터의 논리적 불일치 및 손상을 제한하도록 설계되었으며 여기에는 많은 수준이 있습니다. 데이터베이스 정규화 에 대한 Wikipedia 기사 는 실제로 꽤 좋습니다.

기본적으로 정규화의 첫 번째 규칙 (또는 형식)은 테이블이 관계를 나타내야 함을 나타냅니다. 이는 다음을 의미합니다.

  • 한 행을 다른 행과 구별 할 수 있어야합니다. 즉, 테이블 에 기본 키 역할 을 할 수 있는 항목이 있어야합니다 . 이는 행이 중복되지 않아야 함을 의미합니다.
  • 데이터의 모든 순서는 행의 물리적 순서가 아니라 데이터에 의해 정의되어야합니다 (SQL은 집합 개념을 기반으로합니다. 즉, 사용자가 의존해야하는 유일한 순서는 쿼리에서 명시 적으로 정의하는 순서입니다)
  • 모든 행 / 열 교차에는 하나의 값만 포함되어야합니다.

마지막 요점은 분명히 여기서 두드러진 요점입니다. SQL은 세트를 직접 저장할 수있는 “버킷”을 제공하지 않고 세트를 저장하도록 설계되었습니다. 예, 가능합니다. 아니, 세상은 끝나지 않을 것입니다. 그러나 이미 ORM을 사용하여 즉시 SQL과 함께 제공되는 모범 사례를 이해하는 데 어려움을 겪었습니다. LINQ to SQL은 그래프 계산기와 마찬가지로 환상적입니다. 그러나 같은 맥락에서 그들이 사용하는 프로세스가 실제로 어떻게 작동 하는지를 아는 대신 사용 해서는 안됩니다 .

귀하의 목록은 이제 완전히 “원자 적”일 수 있으며이 프로젝트에서는 변경되지 않을 수 있습니다. 그러나 다른 프로젝트에서 비슷한 일을하는 습관이 생기고 결국에는 (아마도 빨리) 빠르고 쉬운 열 목록을 맞추는 시나리오에 직면하게 될 것입니다. 완전히 부적절한 곳에 접근하십시오. 저장하려는 항목에 대한 올바른 테이블을 만드는 데 추가 작업이 많지 않으며 다른 SQL 개발자가 데이터베이스 디자인을 볼 때 조롱하지 않을 것입니다. 게다가 LINQ to SQL은 사용자의 관계를 확인하고 자동으로 목록에 적절한 개체 지향 인터페이스를 제공합니다 . 비표준적이고 잘못된 데이터베이스 해커를 수행 할 수 있도록 ORM이 제공하는 편의를 포기하는 이유는 무엇입니까?


답변

SQL을 모두 잊어 버리고 “NoSQL”접근 방식을 사용할 수 있습니다. RavenDB , MongoDBCouchDB 는 가능한 솔루션으로 떠 오릅니다 . NoSQL 접근 방식을 사용하면 관계형 모델을 사용하지 않습니다. 스키마에 제한되지 않습니다.


답변

많은 사람들이하는 것을 본 것은 다음과 같습니다 (최선의 접근 방식은 아닐 수 있습니다. 제가 틀렸다면 수정하십시오).

예제에서 사용하는 표는 다음과 같습니다 (표에는 특정 여자 친구에게 부여한 별명이 포함되어 있습니다. 각 여자 친구는 고유 한 ID를가집니다) :

nicknames(id,seq_no,names)

ID 아래에 많은 별명을 저장하려고한다고 가정하십시오. 이것이 우리가 seq_no필드를 포함시킨 이유 입니다.

이제 다음 값을 테이블에 채 웁니다.

(1,1,'sweetheart'), (1,2,'pumpkin'), (2,1,'cutie'), (2,2,'cherry pie')

여자 친구 ID 1에 부여한 모든 이름을 찾으려면 다음을 사용할 수 있습니다.

select names from nicknames where id = 1;


답변

간단한 대답 : 목록이 항상 목록으로 사용된다는 확신이있는 경우에만 목록에서 사용되지 않을 문자 (예 : ‘\ 0’)로 목록을 연결하십시오. 텍스트를 입력하고 저장합니다. 그런 다음 검색 할 때 ‘\ 0’으로 나눌 수 있습니다. 물론이 문제를 해결하는 다른 방법이 있지만 특정 데이터베이스 공급 업체에 따라 다릅니다.

예를 들어 Postgres 데이터베이스에 JSON을 저장할 수 있습니다. 목록이 텍스트이고 더 이상 번거롭지 않고 목록을 원하면 합리적인 타협입니다.

다른 사람들은 직렬화를 제안했지만 직렬화가 좋은 생각이라고는 생각하지 않습니다. 데이터베이스에 대한 깔끔한 부분 중 하나는 서로 다른 언어로 작성된 여러 프로그램이 서로 통신 할 수 있다는 것입니다. 그리고 Java의 형식을 사용하여 직렬화 된 프로그램은 Lisp 프로그램이로드하려는 경우 그다지 잘 수행되지 않습니다.

이런 종류의 일을하는 좋은 방법을 원한다면 일반적으로 배열 또는 유사한 유형을 사용할 수 있습니다. 예를 들어 Postgres는 배열을 유형으로 제공하고 원하는 경우 텍스트 배열을 저장할 수 있으며 JSON을 사용 하는 MySqlMS SQL에 대한 유사한 트릭이 있으며 IBM의 DB2 는 배열 유형도 제공합니다. 자신의 유용한 문서). 이것이 필요하지 않았다면 이것은 그렇게 일반적이지 않을 것입니다.

당신이 그 길을 가면서 잃는 것은 일련의 일들로서 목록의 개념입니다. 최소한 명목상 데이터베이스는 필드를 단일 값으로 취급합니다. 그러나 그것이 당신이 원하는 전부라면, 당신은 그것을해야합니다. 그것은 당신이 스스로 내려야하는 가치 판단입니다.


답변

다른 사람들이 말한 것 외에도 지금보다 더 긴 관점에서 접근 방식을 분석하는 것이 좋습니다. 이다 현재 항목이 고유하는 경우. 이다 현재 항목을 의지하는 새 목록을 필요로하는 경우. 현재 목록이 짧아야합니다. 도메인 세부 사항은 없지만 이러한 요구 사항이 변경 될 수 있다고 생각하는 것은 그리 어렵지 않습니다. 목록을 직렬화하면 좀 더 정규화 된 디자인에 필요하지 않은 비 유연성으로 베이킹됩니다. Btw, 그것은 반드시 완전한 Many : Many 관계를 의미하지는 않습니다. 부모에 대한 외래 키와 항목에 대한 문자 열이있는 단일 자식 테이블을 가질 수 있습니다.

목록을 직렬화하는이 길을 계속 가고 싶다면 목록을 XML로 저장하는 것을 고려할 수 있습니다. SQL Server와 같은 일부 데이터베이스에는 XML 데이터 형식도 있습니다. 내가 XML을 제안하는 유일한 이유는 거의 정의상이 목록이 짧아야하기 때문입니다. 목록이 길면 일반적으로 직렬화하는 것은 끔찍한 접근 방식입니다. CSV 경로로 이동하는 경우 구분 기호가 포함 된 값을 고려해야합니다. 즉, 인용 된 식별자를 사용해야합니다. 목록이 짧다고 가정하면 CSV를 사용하든 XML을 사용하든 별 차이가 없을 것입니다.


답변

난 그냥 CSV로 저장하고, 단순한 값이라면 필요한 모든 것이어야합니다 (XML은 매우 장황하고 그것과 직렬화하는 것은 아마도 과잉 일 수 있지만 옵션이기도합니다).

다음 은 LINQ를 사용하여 CSV를 가져 오는 방법에 대한 좋은 답변 입니다.


답변

목록에서 쿼리해야하는 경우 테이블에 저장하십시오.

항상 목록을 원하면 열에 구분 된 목록으로 저장할 수 있습니다. 이 경우에도 특별한 이유가없는 한 조회 테이블에 저장하십시오.