2016-12-27 51 views
0

我有一个前面的问题,它让我开始,但现在我需要帮助完成此。上一个问题= How to search a string and return only numeric value?在sql中的两个子串之间提取数字

基本上我有一个表,其中包含一个非常长的XML字符串的列之一。最后我想提取一些数字。数目的样本会是这样......

<SendDocument DocumentID="1234567">true</SendDocument> 

所以我想用子,这样我只是在用数字左边找到第一部分= TRUE。

什么我用尽到目前为止是这样的:以上

SELECT SUBSTRING(xml_column, CHARINDEX('>true</SendDocument>', xml_column) - CHARINDEX('<SendDocument',xml_column) +10087,9) 

给我的结果,但它远不是正确的。我担心的是,如果数字从7位数增加到8位数,或者9或10,该怎么办?

在上一问题,我这个帮助:

SELECT SUBSTRING(cip_msg, CHARINDEX('<SendDocument',cip_msg)+26,7) 

和那我怎么开始了,但我想改变这样我就可以减去最后一部分,只是被留下的号码。

所以,再次,包含数字的字符串的第一部分,找到数字周围的两个子字符串并将其删除并检索数字,无论长度如何。

谢谢大家

+0

该示例似乎是错误的...你能更具体吗? – NicoRiff

+0

如果True这个单词后面跟着一串数字,那么你需要做的就是右(LEN(STRING) - POSITION OF TRUE + 1) –

+0

@NicoRiff啊是的,不知道为什么它被切断了,这里又是一次... true

回答

0

您应该能够设置您的SUBSTRING(),以便开始和结束位置都是可变的。这样,数字的长度本身并不重要。

从它的声音,你想要的起始位置是右后的 “真实”

的起始位置是:

CHARINDEX('<SendDocument DocumentID=', xml_column) + 25 
((adding 25 because I think CHARINDEX gives you the position at the beginning of the string you are searching for)) 

长度将是:

CHARINDEX('>true</SendDocument>',xml_column) - CHARINDEX('<SendDocument DocumentID=', xml_column)+25 
((Position of the ending text minus the position of the start text)) 

那么,沿线的东西如何:

SELECT SUBSTRING(xml_column, CHARINDEX('<SendDocument DocumentID=', xml_column)+25,(CHARINDEX('>true</SendDocument>',xml_column) - CHARINDEX('<SendDocument DocumentID=', xml_column)+25)) 
+0

谢谢!这就是除了属于第二个CHARINDEX的最后+25(如果我没有弄错的话)应该是-25。我做了类似的事情,但我没有得到正确的答案,我想我只是放弃了我的想法,不得不问。一段时间后,一切都开始混乱。非常感谢!!还有其他人! –

+0

你会帮我更好地理解语法吗?我被困在第二和第三个charindex中,尝试了解它是如何工作的 –

0

您是否尝试过直接与XML类型的工作?如下图所示:

DECLARE @TempXmlTable TABLE 
(XmlElement xml) 

INSERT INTO @TempXmlTable 
select Convert(xml,'<SendDocument DocumentID="1234567">true</SendDocument>') 



SELECT 
element.value('./@DocumentID', 'varchar(50)') as DocumentID 
FROM 
@TempXmlTable CROSS APPLY 
XmlElement.nodes('//.') AS DocumentID(element) 
WHERE element.value('./@DocumentID', 'varchar(50)') is not null 

如果你只是想这个工作作为一个字符串,你可以做到以下几点:

DECLARE @SearchString varchar(max) = '<SendDocument DocumentID="1234567">true</SendDocument>' 
DECLARE @Start int = (select CHARINDEX('DocumentID="',@SearchString)) + 12 -- 12 Character search pattern 
DECLARE @End int = (select CHARINDEX('">', @SearchString)) - @Start --Find End Characters and subtract start position 

SELECT SUBSTRING(@SearchString,@Start,@End) 

下面是解析XML文档字符串的扩展版本。在下面的示例中,我创建了名为INSTR的PLSQL函数的副本,MS SQL数据库默认情况下不具有此功能。该功能将允许我在指定的起始位置搜索字符串。另外,我正在将一个示例XML字符串解析为一个变量临时表,并将它们视为符合我的搜索条件的行。这是因为可能有许多元素与单词DocumentID,我想要找到所有这些元素。见下:

IF EXISTS (select * from sys.objects where name = 'INSTR' and type = 'FN') 
DROP FUNCTION [dbo].[INSTR] 
GO 

CREATE FUNCTION [dbo].[INSTR] (@String VARCHAR(8000), @SearchStr VARCHAR(255), @Start INT, @Occurrence INT) 
RETURNS INT 
AS 
BEGIN 
DECLARE @Found INT = @Occurrence, 
@Position INT = @Start; 

WHILE 1=1 
BEGIN 
-- Find the next occurrence 
SET @Position = CHARINDEX(@SearchStr, @String, @Position); 

-- Nothing found 
IF @Position IS NULL OR @Position = 0 
RETURN @Position; 

-- The required occurrence found 
IF @Found = 1 
BREAK; 

-- Prepare to find another one occurrence 
SET @Found = @Found - 1; 
SET @Position = @Position + 1; 
END 

RETURN @Position; 
END 
GO 

--Assuming well formated xml 
DECLARE @XmlStringDocument varchar(max) = '<SomeTag Attrib1="5"> 
              <SendDocument DocumentID="1234567">true</SendDocument> 
              <SendDocument DocumentID="1234568">true</SendDocument> 
              </SomeTag>' 

--Split Lines on this element tag 
DECLARE @SplitOn nvarchar(25) = '</SendDocument>' 

--Let's hold all lines in Temp variable table 
DECLARE @XmlStringLines TABLE 
    (
     Value nvarchar(100) 
    ) 

     While (Charindex(@SplitOn,@XmlStringDocument)>0) 
     Begin 

      Insert Into @XmlStringLines (value) 
      Select 
       Value = ltrim(rtrim(Substring(@XmlStringDocument,1,Charindex(@SplitOn,@XmlStringDocument)-1))) 

      Set @XmlStringDocument = Substring(@XmlStringDocument,Charindex(@SplitOn,@XmlStringDocument)+len(@SplitOn),len(@XmlStringDocument)) 
     End 

     Insert Into @XmlStringLines (Value) 
     Select Value = ltrim(rtrim(@XmlStringDocument)) 

    --Now we have a table with multple lines find all Document IDs 
    SELECT 
    StartPosition = CHARINDEX('DocumentID="',Value) + 12, 
    --Now lets use the INSTR function to find the first instance of '">' after our search string 
    EndPosition = dbo.INSTR(Value,'">',(CHARINDEX('DocumentID="',Value)) + 12,1), 
    --Now that we know the start and end lets use substring 
    Value = SUBSTRING(value,( 
       -- Start Position 
       CHARINDEX('DocumentID="',Value)) + 12, 
        --End Position Minus Start Position 
       dbo.INSTR(Value,'">',(CHARINDEX('DocumentID="',Value)) + 12,1) - (CHARINDEX('DocumentID="',Value) + 12)) 
    FROM 
     @XmlStringLines 
    WHERE Value like '%DocumentID%' --Only care about lines with a document id 
+0

是的我有,我已经得到这个工作。但我想有多个选项,因为我也在学习SQL,所以我想弄清楚上面提到的其他方法。 –

+0

我已经编辑了我的回复,只包括使用字符串。 – Mike

+0

阅读你的答案我认为它几乎可以确定的工作,但我得到一个“无效的长度参数传递给左侧或子字符串函数”错误。我对所需的所有帮助表示歉意,但我对SQL很陌生。有什么建议么? –

相关问题