Jamie888 Ответов: 3

Недопустимо на верхнем уровне документа


Привет, у меня есть хранимая процедура, в которой я выберу некоторые детали из БД. Когда я выполняю хранимую процедуру непосредственно с помощью SQL Studio 2016, я получаю ошибку, как показано на заголовке. Хотя я искал в интернете много решений и пробовал их, ни одно из них не может успешно решить мою проблему. Моя хранимая процедура выглядит следующим образом:

DECLARE  
    -- Add the parameters for the stored procedure here  
    @p_CarId NVARCHAR(MAX) = '12345'
--AS  
BEGIN  
-- SET NOCOUNT ON added to prevent extra result sets from  
-- interfering with SELECT statements.  
SET NOCOUNT ON;
    DECLARE @xmlContent AS NVARCHAR(MAX)
    SET @xmlContent = '
    <ROOT>
	   <Vehicles CarId="'+ @p_CarId +'">
	   </Vehicles>
    </ROOT>
    ';

    DECLARE 
	   @hdoc AS INT;  
    EXEC sp_xml_preparedocument @hdoc OUTPUT , @xmlContent  
  
    DECLARE @Car TABLE 
    (  
	   CarId BIGINT
    )   
      
   
    INSERT INTO 
	   @Car  
    SELECT   
	   *  
    FROM   
	   OPENXML(@hdoc,'/ROOT/Vehicles/CarId',1) WITH(CarId BIGINT)  
  
    SELECT   
	     c.CarId  
	    ,cd.CarModel
	    ,cd.CarManufacturedDate
    FROM  
	   @Car AS c
	   INNER JOIN CarDetails AS cd
		  ON c.CarId = cd.CarId 
END


Когда я выполняю приведенный выше сценарий, я продолжаю получать ошибку, как показано в заголовке. Есть какие-нибудь предложения по этому поводу? Спасибо.

Что я уже пробовал:

1. Поиск в интернете возможных объяснений и решений, но безрезультатно.

Santosh kumar Pithani

дайте мне знать, почему вы используете XML-запрос вместо sub-запроса в SP?

3 Ответов

Рейтинг:
2

Richard Deeming

Поскольку вы используете последнюю версию SQL Server, вероятно, было бы проще использовать тип данных XML, а не OPENXML подход:
Тип данных XML и столбцы (SQL Server) | Майкрософт Документы[^]

DECLARE @xmlContent xml = N'
<ROOT>
    <Vehicles CarId="' + CAST(@p_CarId As nvarchar(max)) + N'"/>
</ROOT>
';

DECLARE @Car TABLE 
(  
    CarId BIGINT
);

INSERT INTO @Car
(
    CarId
)
SELECT
    X.V.value('@CarId', 'bigint')
FROM
    @xmlContent.nodes('//Vehicles') As X (V)
;

Но если вы просто пытаетесь передать несколько значений параметру, вам, вероятно, лучше использовать табличный параметр:
Использовать Возвращающие Табличное Значение Параметры (СУБД) Майкрософт Документы[^]


Рейтинг:
1

OriginalGriff

Почти наверняка это ваш "xml": '12345' не является допустимым XML-документом, поэтому этот код:

@p_CarId NVARCHAR(MAX) = '12345'
...
EXEC sp_xml_preparedocument @hdoc OUTPUT , @p_CarId
не соответствует требованиям к параметрам, если только ваш вызов SP не предоставляет допустимое содержимое XML-файла.
Так что проверьте это: посмотрите точно, что вы передаете своему SP, и тщательно проверьте его XML-содержимое. Я подозреваю, что вы вообще не передаете значение или неправильно написали имя параметра, когда пытались.


Цитата:
Здравствуйте, сэр, спасибо за Ваше объяснение. Из-за некоторых обстоятельств я не могу отлаживать свои коды на фактическом входном параметре. Но, основываясь на вашем предложении, я изменил свой вопрос и попытался выполнить его, и теперь ошибка исчезла, хотя и без каких-либо результатов. Не могли бы вы взглянуть на мой обновленный вопрос?


Если я сведу к минимуму ваш обновленный код:
DECLARE @xmlContent AS NVARCHAR(MAX)
    SET @xmlContent = '
    <ROOT>
	   <Vehicles CarId="12345">
	   </Vehicles>
    </ROOT>
    ';

    DECLARE 
	   @hdoc AS INT;  
    EXEC sp_xml_preparedocument @hdoc OUTPUT , @xmlContent 
    
    DECLARE @Car TABLE 
    (  
	   CarId BIGINT
    )   
      
   
    INSERT INTO 
	   @Car  
    SELECT   
	   *  
    FROM   
	   OPENXML(@hdoc,'/ROOT/Vehicles/CarId',1) WITH(CarId BIGINT)  
   SELECT   
	     c.CarId 
И запустите его против SQL Server 2012 SP1, я не получу никакой ошибки. Я тоже не получаю выходных данных, но и не получаю ошибок.
Переходим к этому:
OPENXML(@hdoc,'/ROOT/Vehicles',1) WITH(CarId BIGINT) 
Дает мне одну строку, содержащую "12345", как я и ожидал.

Так что же происходит, когда вы "уменьшаете" свой вклад, чтобы соответствовать моему?


Jamie888

Здравствуйте, сэр, спасибо за Ваше объяснение. Из-за некоторых обстоятельств я не могу отлаживать свои коды на фактическом входном параметре. Но, основываясь на вашем предложении, я изменил свой вопрос и попытался выполнить его, и теперь ошибка исчезла, хотя и без каких-либо результатов. Не могли бы вы взглянуть на мой обновленный вопрос?

OriginalGriff

Смотрите обновленный ответ

Jamie888

я удалил CarId в OPENXML, как и предлагалось, и получил строки записей. Но я все еще не совсем понимаю картину, как удаление Карида может дать результат?

OriginalGriff

Посмотрите на определение OPENXML:
https://docs.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql
Параметр 2-это шаблон строк, а не спецификация столбцов.
Когда вы добавляете CardID в RowPattern, он ожидает, что CardID будет содержать информацию о строке, а не значение элемента одного столбца.

Рейтинг:
0

Santosh kumar Pithani

DECLARE @p_CarId NVARCHAR(MAX) ='12345';
BEGIN
;WITH CTE AS(
          SELECT cd.value('@CarId','Bigint') AS CarId FROM (
		  SELECT  CAST('<ROOT> <Vehicles CarId="'+@p_CarId+'"> </Vehicles> 
                            </ROOT>' AS XML) xmldata
                                                           ) as tab 
		            CROSS APPLY xmldata.nodes('ROOT/*') AS col(cd)
			)
   SELECT   
	     c.CarId  
	    ,cd.CarModel
	    ,cd.CarManufacturedDate
    FROM  
	  CTE AS c
	   INNER JOIN CarDetails AS cd
		  ON c.CarId = cd.CarId 

END;