Другие отметили, что лучшим решением для этого будет изменение дизайна, и я с ними согласен. Однако я также хотел бы отнестись к вашему вопросу как к академическому и ответить на него в случае, если у будущих читателей когда-либо возникнет тот же вопрос в случае использования, когда изменение дизайна было бы невозможным / нежелательным.
Я могу подумать о двух способах сделать то, что вы пытаетесь сделать за один выбор, если нет других ограничений на то, что вы можете сделать, о которых вы еще не упомянули. Для краткости я просто дам вам псевдо-код, который можно адаптировать к вашей ситуации, а также к будущим читателям:
- OPENQUERY (или OPENROWSET)
Вы можете включить свой код выше в хранимую процедуру вместо функции, поскольку хранимые процедуры ДОЛЖНЫ динамически выполнять SQL, в отличие от функций. Тогда запрос SELECT в вашем приложении будет SELECT from OPENQUERY (Выполнить сохраненную процедуру) .
- СОЮЗ ВСЕХ возможностей.
Я почти на 99% уверен, что никто никогда не захочет использовать это, но я упоминаю, что оно настолько полно академически, насколько я знаю, как это сделать.
Вторая возможность будет работать только при наличии ограниченного, известного числа возможных запросов, которые могут поддерживаться вашим приложением. Например, вы можете получить Properties
только от TableA
, отфильтрованного с помощью column1
, или от TableB
, отфильтрованного с помощью Column2
и / или Column3
.
Может быть больше, чем эти возможности, но оно должно быть ограниченным, известным количеством, и чем больше возможностей, тем сложнее и длиннее будет код.
Но если это так, вы можете просто ВЫБРАТЬ из СОЮЗА ВСЕ из всех возможных сценариев и сделать так, чтобы только один из ВЫБОРОВ в СОЮЗЕ ВСЕ возвращал результаты.
Например:
SELECT ... FROM TableA WHERE Column1=fnGetValue(@p, 'Column1')
AND CHARINDEX('SELECT', @property) > 0
AND CHARINDEX('TableA', @property) > 0
AND CHARINDEX('Column1', @property) > 0
AND (Whatever other filters are needed to uniquely identify this case)
UNION ALL
SELECT
...
Обратите внимание, что fnGetValue()
не является встроенной функцией. Вы должны написать это. Он проанализирует строку в @p
, найдет местоположение 'Column1 =' и вернет любое значение, следующее за ним.
В конце вашего UNION ALL вам нужно добавить последний UNION ALL в запрос, который будет обрабатывать случай, когда пользователь передал строку, разделенную запятыми, вместо запроса, но это легко, потому что все шаги в вашем коде, где вы заполняли таблицу переменных, не нужны. Вы можете просто сделать окончательный запрос следующим образом:
WHERE NOT CHARINDEX('SELECT', @p) > 0
AND HMY IN (SELECT strval FROM dbo.StringSplit(@p, ','))
Я почти уверен, что эта возможность требует гораздо больше работы, чем стоит, но это пример того, как в общем случае динамический SQL можно заменить обычным SQL, который просто охватывает все возможные варианты, которые вы хотели, чтобы динамический sql был в состоянии справиться.