Используйте результат одного запроса для создания нового оператора выбора, используя только SQL - PullRequest
0 голосов
/ 18 января 2020

У меня сложилось впечатление, что следующее невозможно с использованием SQL, но я хотел спросить здесь, прежде чем полностью его исключить.

В очень плохо спроектированной БД, которую я должен использовать, одна таблица содержит в качестве значений имена полей другой таблицы. Упрощенно, таблица, назовем ее ColumnTable, выглядит следующим образом:

ID          ColumnName
------      -----------
23          Column_1
24          Column_2

Другая таблица, назовем ее ContentTable, соответственно выглядит следующим образом:

ID          Column_1          Column_2
------      -----------       ----------
101         Somecontent1       Somecontent3
102         Somecontent2       Somecontent4

Как вы можете видите, я не могу использовать внешние ключи, вся БД - это настоящий кошмар. Редизайн БД для приведения его в нормальную форму не вызывает вопросов, поскольку приложение с закрытым исходным кодом зависит от БД, имеющей именно эту схему. Компоновка является скорее реестром, чем реляционной БД.

В любом случае, как вы уже догадались, для запроса содержимого из ContentTable сначала нужно получить имя соответствующего поля. Я совершенно уверен, что приложение делает это в два этапа: сначала оно запрашивает имя поля, затем использует результат этого запроса для создания новой строки запроса для запроса содержимого.

Для примера мы знаем, что мы sh запросим строку с идентификатором 101 в ContentTable, но не знаем, какой столбец. Но мы знаем, что мы можем найти имя столбца в строке с идентификатором 23 из ColumnTable. Я предполагаю, что приложение делает это следующим образом.

int fieldsID = 23
int contentID = 101
string columnName
string neededResult

columnName = SQLQuery("SELECT ColumnName FROM ColumnTable WHERE ID =" + fieldsID)
echo columnName //Will return Column_1

neededResult = SQLQuery("SELECT " + columnName + "FROM ContentTable")
echo neededResult //Will return Somecontent1

Есть ли способ сделать это, используя только SQL?

SELECT (SELECT ColumnName FROM ColumnTable WHERE ID = 1) FROM ContentTable (для получения требуемого оператора выбора SELECT Column_1 FROM ContentTable WHERE ID = 1), очевидно, не будет работать, поскольку вложенный оператор SELECT просто создает новое поле с результатом запроса для содержимого.

Как уже упоминалось, делать это из кода не проблема, но неэффективно. Есть ли способ сделать это в SQL? Хотя этот вопрос относится к SQL в целом, эта спецификация c DB находится в MS SQL, поэтому, если есть какая-то хитрость, чтобы сделать это эффективно в T- SQL, например, с помощью функции или SPRO C Буду признателен за совет.

1 Ответ

2 голосов
/ 18 января 2020

Немного слепое предположение, но, возможно, это то, что вам нужно. Если это равно , то вам действительно нужно исправить дизайн; как вы можете видеть, с такими проблемами очень много проблем.

CREATE TABLE dbo.ColumnTable (ID int,
                              ColumnName sysname); --Tables don't have "fields" that have columns and rows

CREATE TABLE dbo.ContentTable (ID int,
                               Column_1 varchar(50),
                               Column_2 varchar(50));

GO

INSERT INTO dbo.ColumnTable (ID, ColumnName)
VALUES(1,'Column_1'),
      (2,'Column_2');

INSERT INTO dbo.ContentTable (ID, Column_1, Column_2)
VALUES (1,'Somecontent1','Somecontent3'),
       (2,'Somecontent2','Somecontent4');

GO

DECLARE @ColumnID int = 1,
        @ContentID int = 1;

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

SELECT @SQL = N'SELECT ' + QUOTENAME(ColumnName) + @CRLF +
              N'FROM dbo.ContentTable' + @CRLF +
              N'WHERE ID = @ContentID;'
FROM dbo.ColumnTable
WHERE ID = @ColumnID;

EXEC sp_executesql @SQL, N'@ContentID int', @ContentID;
GO

DROP TABLE dbo.ColumnTable;
DROP TABLE dbo.ContentTable;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...