Использование курсора SQL для отображения данных из базы данных

Я делаю приложение C# Windows Form, и оно подключено к базе данных.
Тема: Книжный магазин.

В одной из форм приложения есть DataGridView, который отображает информацию о каждой книге в магазине.
В базе данных одна книга уникальна, со своим ISBN, и разные книги в этом контексте могут иметь одинаковое имя.
Кроме того, у книг может быть много авторов.
Это означает, что когда я делаю запрос, который отображает все книги, он перечисляет одну и ту же книгу более одного раза, чтобы отобразить всех авторов из этой книги.
Я хочу, конечно, перечислить всех авторов в одну колонку, в одну строку, для одной книги.

Мне сказали, что это можно сделать с помощью курсоров.
Но я не представляю, как их использовать.
Мне не нужен точный код, мне просто нужны некоторые рекомендации по решению этой проблемы.

Кроме того, может быть, есть лучший способ сделать это, чем использовать курсоры?


person misty    schedule 19.04.2016    source источник
comment
Я бы посоветовал не использовать курсоры, так как они могут вызвать проблемы с производительностью при запросе в БД. Я рекомендую использовать LINQ to SQL или StoredProcedure для получения результатов из БД. Фактическое решение будет зависеть от вашей структуры класса.   -  person error_handler    schedule 19.04.2016
comment
Вы можете получить помощь здесь: codeproject.com/Articles/63715/BookStore   -  person error_handler    schedule 19.04.2016


Ответы (3)



Вот готовый пример кода, как вы могли бы это сделать (также с тем, что уже было предложено другими). Это то, что вы искали?

-- declare variables

declare @ParamterCurrencyAmount numeric(26, 2),
        @ParameterRollingVisitSum int


-- declare table variable

declare @Books table
(
    ISBN int not null primary key,
    BookName varchar(255) not null
)

-- declare table variable

declare @Authors table
(
    AuthorID int primary key not null,
    AuthorName varchar(255) not null
)

-- declare table variable

declare @BookAuthorRelations table
(
    BookAuthorRelations int not null primary key,
    ISBN int not null,
    AuthorID int not null
)


-- insert sample data 

insert into @Books
(
    ISBN,
    BookName
)
select 1000, 'Book A' union all
select 2000, 'Book B' union all
select 3000, 'Book C'

insert into @Authors
(
    AuthorID,
    AuthorName
)
select 1, 'Jack' union all
select 2, 'Peter' union all
select 3, 'Donald'

insert into @BookAuthorRelations
(
    BookAuthorRelations,
    ISBN,
    AuthorID
)
select 1, 1000, 1 union all
select 2, 1000, 2 union all
select 3, 1000, 3 union all
select 4, 2000, 1 union all
select 5, 2000, 2 union all
select 6, 3000, 1


-- get books (with stuff)

select distinct Books.BookName,
stuff(
        (
            select distinct ', ' + Authors.AuthorName
            from @Authors Authors,
            @BookAuthorRelations BookAuthorRelations
            where BookAuthorRelations.AuthorID = Authors.AuthorID
            and Books.ISBN = BookAuthorRelations.ISBN
            for xml path(''), type
        ).value('.', 'NVARCHAR(MAX)') 
    , 1, 2,'') data
from @Books Books
person Reboon    schedule 19.04.2016
comment
Я думаю, что это он :) Я посмотрю на него позже. - person misty; 19.04.2016
comment
Да, это тот же подход, который я предлагал. Просто для информации - ключевое слово STUFF не является важной частью этой техники, это просто чистый способ удаления ведущей запятой и пробела. (хотя в приведенном выше фрагменте кода его нужно изменить на STUFF(...,1,2,'') - person George Dando; 19.04.2016
comment
Джордж Дандо благодарит за разъяснение, что МАТЕРИАЛ не является важной частью. Я добавил STUFF(... ,1,2,'') к моему образцу, чтобы удалить начальные ,. - person Reboon; 19.04.2016

Если вы работаете с Oracle-DB, вы можете использовать функцию LISTAGG, например:

SELECT listagg(a.author_name, ',') WITHIN GROUP (ORDER BY b.isin) names 
  FROM books b
  join book_authors ba on ba.bookId = b.bookId
  join authors a on a.authorId = ba.authorid
person oratom    schedule 19.04.2016
comment
Каково ваше точное требование? Вы хотите использовать курсор или нет? Как я уже говорил в своем предыдущем комментарии, используйте хранимую процедуру. - person error_handler; 19.04.2016
comment
Хорошо, но здесь вы найдете эквивалент LISTAGG для SQL-сервера stackoverflow.com/questions/15477743/listagg- в SQL-сервере - person oratom; 20.04.2016