Хотя я бы советовал динамическому sql вообще, в этом случае я думаю, вы можете уйти с ним, проверив, содержит ли переменная @Table допустимое имя таблицы.
- Вопрос заключается в том, если вы планируете на позволять имена схем и/или кросс-БД запросов, я предполагаю, что вы не хотите, чтобы выйти из БД (или сервер) здесь, но допускаем для различных схем-х (AdventureWorks показывает, как они могут быть использованы)
- Вы МОЖЕТЕ хотеть также включать представления для @Table.
- Возможно, это было бы «приятно», если бы вы также проверили, есть ли у найденного объекта столбец идентификатора и вызывается ошибка «userfriendly», если нет. Необязательно, хотя.
Простое размещение имени QuoteName() вокруг @table НЕ защитит вас от всего.Хотя это отличная функция, она далека от совершенства. ИМХО лучше всего будет анализировать переменную @Table, проверить, действительно ли ее содержимое, а затем создать динамический sql на основе полученных частей. Я начал делать большую часть выше и удивительно там требует много проверки для чего-то, что выглядит так просто, как это =)
CREATE PROCEDURE [dbo].[GetDataByID] (
@ID bigint,
@Table nvarchar(300)
)
AS
DECLARE @sql nvarchar(max)
DECLARE @server_name sysname,
@db_name sysname,
@schema_name sysname,
@object_name sysname,
@schema_id int
SELECT @server_name = ParseName(@Table, 4),
@db_name = ParseName(@Table, 3),
@schema_name = ParseName(@Table, 2),
@object_name = ParseName(@Table, 1)
IF ISNULL(@server_name, @@SERVERNAME) <> @@SERVERNAME
BEGIN
RaisError('Queries are restricted to this server only.', 16, 1)
Return(-1)
END
IF ISNULL(@db_name, DB_Name()) <> DB_Name()
BEGIN
RaisError('Queries are restricted to this database only.', 16, 1)
Return(-1)
END
IF @schema_name IS NULL
BEGIN
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s]', 16, 1, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
ELSE
BEGIN
SELECT @schema_id = Schema_id(@schema_name)
IF @schema_id IS NULL
BEGIN
RaisError('Unrecognized schema requested [%s].', 16, 1, @schema_name)
Return(-1)
END
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND schema_id = @schema_id
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s].[%s]', 16, 1, @schema_name, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@schema_name) + '.' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
EXEC sp_executesql @stmt = @sql,
@params = N'@ID bigint',
@ID = @ID
Return(0)
Supra компилируется, но вы, возможно, придется сглаживать некоторые ошибки, как я Ждут» t достаточно дойти до проверки всех кодов.
Просто крошечная вещь, которая не сильно влияет на вещи, но разве это не проблема '@ Table', это проблема? '@ ID' является' bigint', поэтому это может быть только число, когда вы достигаете точки построения динамического оператора SQL, не так ли? –
Я полагаю, что оба .. –