SQL Server 2008 - Как конвертировать ntext в список int? - PullRequest
0 голосов
/ 31 декабря 2011

У меня есть столбец с типом ntext, и я хотел бы преобразовать его в список int.Столбец называется ValidForCustomers и содержит идентификаторы клиентов, разделенные запятой.

Я знаю, что могу привести его к nvarchar(max), но когда я делаю это, SQL выдает ошибку

Неверный синтаксис рядом с'.'.

Часть запроса

select Items from Split(c.ValidForCustomers, ',')

Это запрос

select top 100 
*,c.CouponCode, 
c.Description,
case when c.CouponType = 0 then 'Order - this coupon ONLY applies to the order subtotal'
else 'Product - this coupon ONLY applies to the specified product(s)' end as CouponType,
case when c.DiscountIncludesFreeShipping = 0 then 'No' else 'Yes' end as FreeShiping,
case when c.ExpiresAfterOneUsageByEachCustomer = 0 then 'No' else 'Yes' end as 'ExpiresAfterOneUsageByAnyCustomer',
case when c.ExpiresOnFirstUseByAnyCustomer = 0 then 'No' else 'Yes' end as 'ExpiresOnFirstUseByAnyCustomer',
c.ExpiresAfterNUses,
case when len(CAST(c.ValidForCustomers as nvarchar(max))) = 0 THEN 'No'
    ELSE cstms.CustomerNames END as 'ValidForCustomers',
CASE when LEN(CAST(c.ValidForProducts as nvarchar(max))) = 0 THEN 'No' ELSE 'No' END as 'ValidForProducts',
CASE when LEN(CAST(c.ValidForCategories as nvarchar(max))) = 0 THEN 'No' ELSE 'Yes' END as 'ValidForCategories'
    from Coupon c with(nolock)        
    cross apply ( select CustomerNames = (SELECT SUBSTRING((SELECT ',' + cust.FirstName + ' ' + cust.LastName
                FROM Customer cust
                inner join (select IntegerFromList from dbo.fn_StringListToIntList(CAST(c.ValidFOrCustomers as nvarchar(max)), ',')) sp on (sp.IntegerFromList= cust.CustomerID)                
                ORDER BY cust.FirstName
                FOR XML PATH('')),2,200000))) as cstms

Это процедура преобразования

CREATE FUNCTION [dbo].[fn_StringListToIntList]
(
  @IntegerList  NVARCHAR(MAX),
  @Delimiter    CHAR(1) = '|'
)
RETURNS @IntegersTable TABLE (IntegerFromList  INT)
AS
BEGIN
  IF (@IntegerList IS NULL) OR (LEN(@IntegerList) = 0) OR (@Delimiter IS NULL) RETURN

  DECLARE  @DelimPos INT
  SELECT  @DelimPos = PATINDEX('%' + @Delimiter + '%', @IntegerList)

  WHILE @DelimPos <> 0
  BEGIN
    --If nothing between delims, save as NULL
    IF LEN(SUBSTRING(@IntegerList, 1, @DelimPos - 1)) = 0
      INSERT INTO @IntegersTable(IntegerFromList)  VALUES(NULL)
    ELSE
      INSERT INTO @IntegersTable(IntegerFromList)
      VALUES(CONVERT(INT, SUBSTRING(@IntegerList, 1, @DelimPos - 1)))

    SELECT @IntegerList  = SUBSTRING(@IntegerList, @DelimPos + 1, LEN(@IntegerList))
    SELECT @DelimPos  = PATINDEX('%' + @Delimiter + '%', @IntegerList)
  END --While...

  --If no additional chars after a final delim, treat as an additional NULL
  IF LEN(@IntegerList) = 0
    INSERT INTO @IntegersTable(IntegerFromList)  VALUES(NULL)
  ELSE
    INSERT INTO @IntegersTable(IntegerFromList)  VALUES(CONVERT(INT, @IntegerList))

  RETURN 

END --Function

и ошибка

Msg 102, Level 15, State 1, Line 17
Incorrect syntax near '('.

и все в порядке с синтаксисом

Ответы [ 3 ]

0 голосов
/ 31 декабря 2011

Поскольку все номера являются идентификаторами клиентов, вместо этого вы можете проверить идентификатор каждого клиента, чтобы проверить, есть ли он в списке.

SELECT Customer.Id
FROM MyTableWithTextField
INNER JOIN Customer
ON MyTableWithTextField.TextField LIKE CAST(Customer.Id AS VARCHAR(10)) + ',%'
OR MyTableWithTextField.TextField LIKE '%,' + CAST(Customer.Id AS VARCHAR(10)) + ',%'
OR MyTableWithTextField.TextField LIKE '%,' + CAST(Customer.Id AS VARCHAR(10))

Да, это отвратительно и, вероятно, будет плохо работать, но это неизбежно, если вы попытаетесь сохранить переменное количество значений в одном поле. Гораздо лучшая идея - создать новую таблицу.

0 голосов
/ 31 декабря 2011

Я создал пользовательскую функцию для возврата строки клиентов,

ALTER FUNCTION [dbo].[fn_GetCustomersForCoupon](
    @CouponID int
)
returns nvarchar(MAX)
as
Begin
declare @Str nvarchar(max)
declare @IntTable table ( ID int)
declare @ValidForProducts nvarchar(2000)

select @ValidForProducts = ValidForCustomers from Coupon where CouponID=@CouponID
insert into @IntTable (ID) select * from dbo.fnStringListToIntList(@ValidForProducts, ',')
SELECT @Str = SUBSTRING((select ',' + Replace(p.FirstName + ' ' + p.LastName, '<Name>','') from @IntTable t
inner join Customer p on (p.CustomerID = t.ID)
FOR XML PATH('')),2,200000)

return @Str
end

теперь он работает как талисман, но напрямую из запроса, как подзапрос, он не работает.

0 голосов
/ 31 декабря 2011

Это был бы хороший синтаксис для cast:

select  *
from    dbo.Split(cast(c.ValidForCustomers as nvarchar(max)), ',')

Это выдает ошибку?

Схема dbo не является обязательной при вызове пользователя-определенная функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...