code

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

codestyles 2020. 8. 25. 08:03
반응형

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


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

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;

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

If you still want to go down this road of serializing the list, you might consider storing the list in XML. Some databases such as SQL Server even have an XML data type. The only reason I'd suggest XML is that almost by definition, this list needs to be short. If the list is long, then serializing it in general is an awful approach. If you go the CSV route, you need to account for the values containing the delimiter which means you are compelled to use quoted identifiers. Persuming that the lists are short, it probably will not make much difference whether you use CSV or XML.


If you need to query on the list, then store it in a table.

If you always want the list, you could store it as a delimited list in a column. Even in this case, unless you have VERY specific reasons not to, store it in a lookup table.


Simple answer: If, and only if, you're certain that the list will always be used as a list, then join the list together on your end with a character (such as '\0') that will not be used in the text ever, and store that. Then when you retrieve it, you can split by '\0'. There are of course other ways of going about this stuff, but those are dependent on your specific database vendor.

As an example, you can store JSON in a Postgres database. If your list is text, and you just want the list without further hassle, that's a reasonable compromise.

Others have ventured suggestions of serializing, but I don't really think that serializing is a good idea: Part of the neat thing about databases is that several programs written in different languages can talk to one another. And programs serialized using Java's format would not do all that well if a Lisp program wanted to load it.

If you want a good way to do this sort of thing there are usually array-or-similar types available. Postgres for instance, offers array as a type, and lets you store an array of text, if that's what you want, and there are similar tricks for MySql and MS SQL using JSON, and IBM's DB2 offer an array type as well (in their own helpful documentation). This would not be so common if there wasn't a need for this.

What you do lose by going that road is the notion of the list as a bunch of things in sequence. At least nominally, databases treat fields as single values. But if that's all you want, then you should go for it. It's a value judgement you have to make for yourself.


I'd just store it as CSV, if it's simple values then it should be all you need (XML is very verbose and serializing to/from it would probably be overkill but that would be an option as well).

Here's a good answer for how to pull out CSVs with LINQ.


Only one option doesn't mentioned in the answers. You can de-normalize your DB design. So you need two tables. One table contains proper list, one item per row, another table contains whole list in one column (coma-separated, for example).

Here it is 'traditional' DB design:

List(ListID, ListName) 
Item(ItemID,ItemName) 
List_Item(ListID, ItemID, SortOrder)

Here it is de-normalized table:

Lists(ListID, ListContent)

The idea here - you maintain Lists table using triggers or application code. Every time you modify List_Item content, appropriate rows in Lists get updated automatically. If you mostly read lists it could work quite fine. Pros - you can read lists in one statement. Cons - updates take more time and efforts.


If you really wanted to store it in a column and have it queryable a lot of databases support XML now. If not querying you can store them as comma separated values and parse them out with a function when you need them separated. I agree with everyone else though if you are looking to use a relational database a big part of normalization is the separating of data like that. I am not saying that all data fits a relational database though. You could always look into other types of databases if a lot of your data doesn't fit the model.


I think in certain cases, you can create a FAKE "list" of items in the database, for example, the merchandise has a few pictures to show its details, you can concatenate all the IDs of pictures split by comma and store the string into the DB, then you just need to parse the string when you need it. I am working on a website now and I am planning to use this way.

참고URL : https://stackoverflow.com/questions/3070384/how-to-store-a-list-in-a-column-of-a-database-table

반응형