我有两个表主和详细信息。我将xml传递给存储过程作为参数值,但是当执行存储过程代码时,则不会插入任何数据,也不会引发任何错误。我无法理解问题所在。
任何人都可以帮助我在导致问题的商店过程代码中找到错误的区域。
/bin/bash: warning: here-document at line 0 delimited by end-of-file (wanted 'Kaggle username')
/bin/bash: warning: here-document at line 0 delimited by end-of-file (wanted `Kaggle password')
/usr/local/lib/python3.6/dist-packages/mechanicalsoup/browser.py:37: UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.
The code that caused this warning is on line 37 of the file /usr/local/lib/python3.6/dist-packages/mechanicalsoup/browser.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.
response.content, **soup_config)
'Response' object has no attribute 'soup'
我这样解决了
Table code
-------------
CREATE TABLE TblTickerTemplate (
ID int identity,
Ticker varchar(20),
LineItem varchar(100),
Insertdate datetime DEFAULT GETDATE()
CONSTRAINT PK_ID PRIMARY KEY CLUSTERED (ID)
);
ALTER Table TblTickerTemplate
Add CONSTRAINT UC_Ticker_LineItem UNIQUE (Ticker, LineItem)
CREATE TABLE TblTickerTemplateDetail (
MasterTemplateID int,
ID int identity,
LineItem varchar(100),
XFundCode varchar(100),
Action Char(1),
UserID varchar(20),
Insertdate datetime DEFAULT GETDATE()
FOREIGN KEY(MasterTemplateID) REFERENCES TblTickerTemplate(ID)
);
Procedure code
-------------
ALTER Procedure USP_InsertUniqueLineItems
(
@INPUTXML xml,
@STATUS VARCHAR(MAX) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION
BEGIN TRY
Declare @TblTickerTemplateDetailID AS INT
Declare @XMLFormat AS INT
Declare @Ticker AS VARCHAR(MAX)
Declare @ID AS INT
Declare @Lineitem AS VARCHAR(MAX)
Declare @XFundCode AS VARCHAR(MAX)
Declare @UserID AS VARCHAR(MAX)
--load xml data into cursor
Exec sp_xml_preparedocument @XMLFormat OUTPUT, @INPUTXML
DECLARE CURRECORD
CURSOR LOCAL FOR
SELECT Ticker,ID,Lineitem,XFundCode,@UserID
FROM OPENXML (@XMLFORMAT, '/Lineitems', 1)
WITH (
Ticker VARCHAR(MAX),
ID INT,
Lineitem VARCHAR(MAX),
XFundCode VARCHAR(MAX),
UserID VARCHAR(MAX)
)
SET @TblTickerTemplateDetailID = 0
-- open cursor
OPEN CURRECORD
FETCH NEXT FROM CURRECORD INTO @Ticker,@ID,@Lineitem,@XFundCode,@UserID
-- iterate in cursor to fetch value
WHILE (@@FETCH_STATUS=0)
BEGIN
-- if ID == 0 then new data it will be inserted in TblTickerTemplate & TblTickerTemplateDetail table
IF @ID = 0
BEGIN
IF NOT EXISTS(SELECT LineItem FROM TblTickerTemplate WHERE LineItem = @Lineitem AND Ticker = @Ticker)
BEGIN
INSERT INTO TblTickerTemplate(Ticker,LineItem)
VALUES (@Ticker,@Lineitem)
SET @TblTickerTemplateDetailID = SCOPE_IDENTITY()
INSERT INTO TblTickerTemplateDetail (MasterTemplateID,LineItem,XFundCode,UserID,[Action])
VALUES (@TblTickerTemplateDetailID,@Lineitem,@XFundCode,@UserID,'I')
END
END
ELSE
BEGIN
-- if ID > 0 means existing data & the data will be inserted in TblTickerTemplateDetail table only
INSERT INTO TblTickerTemplateDetail (MasterTemplateID,LineItem,XFundCode,UserID,[Action])
VALUES (@ID,@Lineitem,@XFundCode,@UserID,'U')
END
FETCH NEXT FROM CURRECORD INTO @Ticker,@ID,@Lineitem,@XFundCode,@UserID
END
IF @ID = 0
BEGIN
SET @STATUS='New Line items successfully inserted'
END
ELSE IF @ID > 0
BEGIN
SET @STATUS='Existing Line items successfully updated'
END
CLOSE CURRECORD
DEALLOCATE CURRECORD
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE @ERROR INT, @MESSAGE VARCHAR(4000)
SELECT @ERROR = ERROR_NUMBER(),@MESSAGE = ERROR_MESSAGE()
--SET @STATUS='Line items insert fail'
ROLLBACK TRANSACTION
RAISERROR ('USP_InsertUniqueLineItems:', 16, 1, @ERROR, @MESSAGE)
--SET @STATUS='Fail-- '+@MESSAGE
--RETURN
END CATCH;
SET NOCOUNT OFF
END
Calling procedure this way
--------------------------
Declare @inputxml xml
Declare @Status VARCHAR(MAX)
set @inputxml='<Lineitems>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Net Revenue</LineItem>
<XFundCode>TRIN</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Cost of Revenue</LineItem>
<XFundCode>XXP</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
</Lineitems>'
EXEC [dbo].USP_InsertUniqueLineItems @inputxml, @Status output
Select @Status
但是,如果我取消注释此行/*
SAMPLE XML to insert
<Lineitems>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Net Revenue</LineItem>
<XFundCode>TRIN</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
<Lineitem>
<Ticker>TER</Ticker>
<ID>0</ID>
<LineItem>Cost of Revenue</LineItem>
<XFundCode>XXP</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
</Lineitems>
*/
ALTER Procedure USP_InsertUniqueLineItems
(
@INPUTXML xml,
@STATUS VARCHAR(MAX) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION
BEGIN TRY
Declare @TblTickerTemplateDetailID AS INT
Declare @XMLFormat AS INT
Declare @Ticker AS VARCHAR(MAX)
Declare @ID AS INT
Declare @Lineitem AS VARCHAR(MAX)
Declare @XFundCode AS VARCHAR(MAX)
Declare @UserID AS VARCHAR(MAX)
--load xml data into cursor
Exec sp_xml_preparedocument @XMLFormat OUTPUT, @INPUTXML
DECLARE CURRECORD
CURSOR LOCAL FOR
SELECT ID,Ticker,LineItem,XFundCode,UserID
FROM OPENXML (@XMLFORMAT, '/Lineitems/Lineitem', 2)
WITH (
ID INT,
Ticker VARCHAR(MAX),
LineItem VARCHAR(MAX),
XFundCode VARCHAR(MAX),
UserID VARCHAR(MAX)
)
SET @TblTickerTemplateDetailID = 0
-- open cursor
OPEN CURRECORD
FETCH NEXT FROM CURRECORD INTO @ID,@Ticker,@Lineitem,@XFundCode,@UserID
-- iterate in cursor to fetch value
WHILE (@@FETCH_STATUS=0)
BEGIN
-- if ID == 0 then new data it will be inserted in TblTickerTemplate & TblTickerTemplateDetail table
IF @ID = 0
BEGIN
IF NOT EXISTS(SELECT * FROM TblTickerTemplate WHERE LineItem = @Lineitem AND Ticker = @Ticker)
BEGIN
Print @Ticker+' '+@Lineitem
INSERT INTO TblTickerTemplate(Ticker,LineItem)
VALUES (@Ticker,@Lineitem)
SET @TblTickerTemplateDetailID = SCOPE_IDENTITY()
SET @STATUS='New Line items successfully inserted'
INSERT INTO TblTickerTemplateDetail (MasterTemplateID,LineItem,XFundCode,UserID,[Action])
VALUES (@TblTickerTemplateDetailID,@Lineitem,@XFundCode,@UserID,'I')
END
END
ELSE
BEGIN
-- if ID > 0 means existing data & the data will be inserted in TblTickerTemplateDetail table only
INSERT INTO TblTickerTemplateDetail (MasterTemplateID,LineItem,XFundCode,UserID,[Action])
VALUES (@ID,@Lineitem,@XFundCode,@UserID,'U')
END
FETCH NEXT FROM CURRECORD INTO @ID,@Ticker,@Lineitem,@XFundCode,@UserID
END
-- storing message to OUTPUT type variable
IF @ID = 0
BEGIN
SET @STATUS='New Line items successfully inserted'
END
ELSE IF @ID > 0
BEGIN
SET @STATUS='Existing Line items successfully updated'
END
CLOSE CURRECORD
DEALLOCATE CURRECORD
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- Error handling part
DECLARE @ERROR INT, @MESSAGE VARCHAR(4000)
SELECT @ERROR = ERROR_NUMBER(),@MESSAGE = ERROR_MESSAGE()
SET @STATUS='Fail-- '+@MESSAGE
ROLLBACK TRANSACTION
--RAISERROR ('USP_InsertUniqueLineItems:', 16, 1, @ERROR, @MESSAGE)
RETURN
END CATCH;
SET NOCOUNT OFF
END
,那么错误就来了。如何解决...分享一些想法。谢谢
答案 0 :(得分:1)
嗨,请在插入时尝试使用此代码。
Declare @inputxml xml
set @inputxml='<Lineitems>
<Lineitem>
<Ticker>TER</Ticker>
<ID>1</ID>
<LineItem>Net Revenue</LineItem>
<XFundCode>TRIN</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
<Lineitem>
<Ticker>TER</Ticker>
<ID>2</ID>
<LineItem>Cost of Revenue</LineItem>
<XFundCode>XXP</XFundCode>
<UserID>TDP</UserID>
</Lineitem>
</Lineitems>'
SELECT
T.C.value('(ID)[1]', 'int')
,T.C.value('(Ticker)[1]', 'varchar(max)')
,T.C.value('(LineItem)[1]', 'varchar(max)')
,T.C.value('(XFundCode)[1]', 'varchar(max)')
,T.C.value('(UserID)[1]', 'varchar(max)')
FROM @inputxml.nodes('Lineitems/Lineitem') T(C)
请根据您在select语句中的要求更改变量数据类型,否则将是您的错误。
答案 1 :(得分:1)
您的代码有很多问题,我想算的不胜枚举。看起来它确实是从SQL Server 2000数据库移植而来,只是添加了一些最少的附加内容,例如try / catch
块和max
数据类型。
基本上,您的整个TRY
可以用以下2条语句代替:
insert into dbo.TblTickerTemplate (LineItem, Ticker)
select t.c.value('(./LineItem/text())[1]', 'varchar(100)'),
t.c.value('(./Ticker/text())[1]', 'varchar(100)')
from @inputxml.nodes('./Lineitems[1]/Lineitem[(./ID/text())[1] = "0"]') t(c);
insert into dbo.TblTickerTemplateDetail ([Action], LineItem, MasterTemplateID, UserID, XFundCode)
select case t.c.value('(./ID/text())[1]', 'int') when 0 then 'I' else 'U' end as [Action],
t.c.value('(./LineItem/text())[1]', 'varchar(100)') as [LineItem],
m.ID as [MasterTemplateId],
t.c.value('(./UserID/text())[1]', 'varchar(20)') as [UserId],
t.c.value('(./XFundCode/text())[1]', 'varchar(100)') as [XFundCode]
from dbo.TblTickerTemplate m
inner join @inputxml.nodes('./Lineitems[1]/Lineitem') t(c) on
m.LineItem = t.c.value('(./LineItem/text())[1]', 'varchar(100)')
and m.Ticker = t.c.value('(./Ticker/text())[1]', 'varchar(100)');
并不是特别理想-对于大小合适的XML(100多个节点),通常最好先以关系形式缓存数据,要么将其存储在@table变量(它们已经存在于2000年,是的)中,要么存储在#temporary表中。另外,在第一个插入中,您将要添加存在检查,以使新插入的行不会破坏您的自然键。但是作为骨架,是的。
我注意到的另一件事是./UserID
属性实际上从未使用过-您的代码将@UserID
变量放入游标声明中,然后将变量(即NULL
(此时)在fetch next
中分配给自己。毫无疑问,有错字或复制粘贴。
答案 2 :(得分:0)
存储过程不会无误地添加任何数据
这是因为OPENXML只是返回NULL。
SELECT Ticker,ID,Lineitem,XFundCode,@UserID
FROM OPENXML (@XMLFORMAT, '/Lineitems', 1)
WITH (
Ticker VARCHAR(MAX),
ID INT,
Lineitem VARCHAR(MAX),
XFundCode VARCHAR(MAX),
UserID VARCHAR(MAX)
);
应为:
SELECT Ticker,ID,Lineitem,XFundCode,@UserID
FROM OPENXML (@XMLFORMAT, '/Lineitems/Lineitem', 2)
WITH (
Ticker VARCHAR(MAX),
ID INT,
Lineitem VARCHAR(MAX),
XFundCode VARCHAR(MAX),
UserID VARCHAR(MAX)
)
请注意,将OPENXML的模式从 1(以属性为中心)更改为 2(以元素为中心),并将'/Lineitems'
更改为{{1} }。
也:'/Lineitems/Lineitem'
应该有相应的Exec sp_xml_preparedocument
。
总结:我同意你应该避免使用EXEC sp_xml_removedocument
并使用sp_xml_preparedocument/OPENXML/CURSOR
语法完全重写它的评论。