The identifier that starts with (query) Maximum length is 128 - sql

Problem: I am using a sp on sql server where I took parameter which modify the query and then run the full query in the server. While I am passing that parameter to sp then it says: "The identifier that starts with 'WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-001' is too long. Maximum length is 128."
THE QUERY:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[get_SupComProducts] #whereClause NVARCHAR(max)
AS
BEGIN
DECLARE #query NVARCHAR(max)
, #status VARCHAR(25);
SET #status = 'IN'
SET #query = 'SELECT DISTINCT
p.ProductId,
p.CompanyId,
p.ProductName,
p.ProductGrossWeight,
p.ProductNetWeight,
p.ProductUnit,
p.CategoryId,
p.BrandId,
p.ProductBarcode,
p.MinShelfLife,
p.ProductMargin,
p.IsWeighted,
p.PVAT,
p.ProductMargin,
p.AFSProduct,
ISNULL(sp.ProductBarcode, 0) AS Barcode,
ISNULL(sp.CostPrice, 0) AS CostPrice,
ISNULL(sp.TradePrice, 0) AS TradePrice,
ISNULL(sp.MRP, 0) AS MRP,
ISNULL(sp.SellingPrice, 0) AS SellingPrice,
ISNULL(sp.VAT, 0) AS VAT,
ISNULL((
SELECT SUM(ProductQty) AS ProductQty
FROM StockDetails
WHERE ProductId = p.ProductId AND [Status]= ''' + #status + '''' +
'),0) AS CurrentStock
FROM Supplier d
JOIN Product p
ON p.CompanyId = d.CompanyId
LEFT JOIN StockDetails sd
ON sd.ProductId = p.ProductId
LEFT JOIN SupplierProduct sp
ON sp.ProductId = p.ProductId ' + #whereClause
EXEC (#query)
END
GO
Please if there are any resolve you guys know already, it will be much appreciable. Thanks in advance.
SP EXEC:
EXEC [dbo].[get_SupComProducts] #whereClause="WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-00123'"
If I remove any of the AND query then it works, but the full query says the error.
Msg 103, Level 15, State 4, Line 1
The identifier that starts with 'WHERE d.LastModified<1676270281779 AND (p.ProductName LIKE '%2004%' OR p.ProductBarcode LIKE '%2004%') AND d.SupplierId='SUP-001' is too long. Maximum length is 128.

While there might be issues with your procedure, this particular one comes from the way you call it. Double quotes in SQL, by default, designate object names, and in MS SQL Server, maximum length for any object name is 128 characters. That's where you are getting this error, I suspect.
So, in your sp call, you need to replace your double quotes with single ones, and appropriately escape all single quotes inside it. Something like this:
EXEC [dbo].[get_SupComProducts] #whereClause = '
WHERE
d.LastModified<1676270281779 AND (
p.ProductName LIKE ''%2004%''
OR p.ProductBarcode LIKE ''%2004%''
) AND d.SupplierId=''SUP-00123''
';

Related

How to execute exceeded length query

The character string that starts with '"0111" OR "0112" OR "0115" OR ' is too long. Maximum length is 4000.
declare #stmt1 varchar(max)
set #stmt1='insert into dbo.abcd SELECT [company],[address],
[address2],[zip],[zip4],[city],[state],
[telephone_number],LOWER([email]),[name],[fname],[mname],[lname],
[title_full] FROM DBO.filter WHERE
[id] in (''7'',''8'',''11'',''15'') and contains
(code,'+''''+'"0111" OR "4142"......................OR
"5999"'+''''+')'
exec (#stmt1) AT [server]
Try this:
declare #stmt1 varchar(max)
set #stmt1=CAST('insert into dbo.abcd SELECT [company],[address],
[address2],[zip],[zip4],[city],[state],
[telephone_number],LOWER([email]),[name],[fname],[mname],[lname],
[title_full] FROM DBO.filter WHERE
[id] in (''7'',''8'',''11'',''15'') and contains
(code,' AS VARCHAR(MAX))+''''+'"0111" OR "4142"......................OR
"5999"'+''''+')'
exec (#stmt1) AT [server]
Assuming that your codes list are stored in a table, say 'dbo.codes', with a field 'code' containing the value, you can avoid the CONTAINS predicate and use an INNER JOIN between the two tables using LIKE.
DECLARE #stmt1 VARCHAR(MAX)
SET #stmt1 = 'INSERT INTO dbo.abcd
SELECT DISTINCT [F].[company], [F].[address], [F].[address2], [F].[zip], [F].[zip4],
[F].[city], [F].[state], [F].[telephone_number], LOWER([F].[email]),
[F].[name], [F].[fname], [F].[mname], [F].[lname], [F].[title_full]
FROM dbo.filter AS F INNER JOIN dbo.codes AS C ON F.code LIKE ''%'' + C.code + ''%''
WHERE (F.id in (''7'',''8'',''11'',''15''))';
EXEC (#stmt1) AT [server]

SELECT Column AS #ParameterName in SQL Server stored procedure

I have a stored procedure and I need to pass in a column alias as a parameter, how can I make this work?
This is the line of the stored procedure giving me trouble:
ManufacturerPriceListQty.Price As #PriceLevelAlias
and here is the stored procedure:
ALTER PROCEDURE [dbo].[Export_Products]
#PriceLevelAlias AS VARCHAR(25),
#PriceListCodes AS VARCHAR(250) --Exmaple: 'Des', 'Designer', 'Non-Stocking', 'NonStocking'
AS
BEGIN
SET NOCOUNT ON;
--PRINT #PriceListCodes
--SELECT * FROM dbo.Split(#PriceListCodes,',')
-- Insert statements for procedure here
SELECT
CAST(p.ManufacturerID as varchar(2))+'-'+p.ProductNumber AS ItemID,
SUBSTRING(p.ProductName,0,100) as ItemName,
p.ProductName AS [Description],
ManufacturerPriceListQty.Price As #PriceLevelAlias,
ManufacturerPriceListQty.Qty as OnHandQuantity,
ManufacturerPriceListQty.MultipleQty as OrderMinimumQuantity,
ManufacturerPriceListQty.MultipleQty as OrderMultipleQuantity,
Manufacturer.CompanyName AS CatalogName,
Manufacturer.CompanyName AS CatalogCode,
p.ProductNumber as UDF1,
CAST(p.ManufacturerID as varchar(2)) AS UDF2,
'%'+CAST(p.ProductID as varchar(10)) as UDF5,
CASE
WHEN P.Active ='1' THEN 'FALSE'
ELSE 'TRUE'
END AS IsDeleted,
#PriceLevelAlias AS PriceLevel,
ManufacturerPriceList.PriceListCode,
ManufacturerPriceListProduct.PriceListID
FROM
ManufacturerPriceListProduct
INNER JOIN
ManufacturerPriceList ON ManufacturerPriceListProduct.PriceListID = ManufacturerPriceList.PriceListID
INNER JOIN
Manufacturer ON ManufacturerPriceList.ManufacturerID = Manufacturer.ManufacturerID
INNER JOIN
ManufacturerPriceListQty ON ManufacturerPriceListProduct.PriceListProductID = ManufacturerPriceListQty.PriceListProductID
INNER JOIN
Product p ON ManufacturerPriceListProduct.ProductID = p.ProductID
WHERE
(Manufacturer.Active = 1)
AND p.Discontinued = 0
AND PriceListCode IN (SELECT * FROM dbo.Split(#PriceListCodes, ','))
END
instead of the direct script, try using the final select statement as Query string. Try the below :
ALTER PROCEDURE [dbo].[Export_Products]
#PriceLevelAlias AS VARCHAR(25),
#PriceListCodes AS VARCHAR(250) --Exmaple: 'Des', 'Designer', 'Non-Stocking', 'NonStocking'
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--PRINT #PriceListCodes
--SELECT * FROM dbo.Split(#PriceListCodes,',')
-- Insert statements for procedure here
DECLARE #v_Qry VARCHAR(MAX)
SELECT
#v_Qry = '
SELECT
CAST(p.ManufacturerID as varchar(2))+''-''+p.ProductNumber AS ItemID
,SUBSTRING(p.ProductName,0,100) as ItemName
,p.ProductName AS [Description]
,ManufacturerPriceListQty.Price As '+#PriceLevelAlias+'
,ManufacturerPriceListQty.Qty as OnHandQuantity
,ManufacturerPriceListQty.MultipleQty as OrderMinimumQuantity
,ManufacturerPriceListQty.MultipleQty as OrderMultipleQuantity
,Manufacturer.CompanyName AS CatalogName
,Manufacturer.CompanyName AS CatalogCode
,p.ProductNumber as UDF1
,CAST(p.ManufacturerID as varchar(2)) AS UDF2
,''%''+CAST(p.ProductID as varchar(10)) as UDF5
,CASE
WHEN P.Active =''1'' THEN ''FALSE''
ELSE ''TRUE''
END AS IsDeleted
,#PriceLevelAlias AS PriceLevel
,ManufacturerPriceList.PriceListCode
,ManufacturerPriceListProduct.PriceListID
FROM ManufacturerPriceListProduct INNER JOIN
ManufacturerPriceList ON ManufacturerPriceListProduct.PriceListID = ManufacturerPriceList.PriceListID INNER JOIN
Manufacturer ON ManufacturerPriceList.ManufacturerID = Manufacturer.ManufacturerID INNER JOIN
ManufacturerPriceListQty ON ManufacturerPriceListProduct.PriceListProductID = ManufacturerPriceListQty.PriceListProductID INNER JOIN
Product p ON ManufacturerPriceListProduct.ProductID = p.ProductID
WHERE (Manufacturer.Active = 1)
AND p.Discontinued=0
AND PriceListCode
IN(SELECT * FROM dbo.Split(#PriceListCodes,'',''))'
EXEC(#v_Qry)
END
It is not possible to set a column's alias dynamically. The only way to achieve this, is to create the full statement dynamically (there is an answer already).
With a closed set of possible values you could use a structure with IF to define your statement in all possible combinations.
The following might help you, if you have a closed set of values and the calling code knows, which column name is to be used.
As your SP is returning a result set, you might include the same value with all possible names. Look at this example
SELECT *
,type_desc AS Name1
,type_desc AS Name2
,type_desc AS Name3
--add all possible types here
FROM sys.objects
Which column you use after the call, will then be the decision of the calling code...
There were two other variables that need to be taken outside of the string:
`ALTER PROCEDURE [dbo].[Export_Products]
#PriceLevelAlias AS VARCHAR(25),
#PriceListCodes AS VARCHAR(250) --Exmaple: 'Des', 'Designer', 'Non-Stocking', 'NonStocking'
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--PRINT #PriceListCodes
--SELECT * FROM dbo.Split(#PriceListCodes,',')
-- Insert statements for procedure here
DECLARE #v_Qry VARCHAR(MAX)
SELECT
#v_Qry = '
SELECT
CAST(p.ManufacturerID as varchar(2))+''-''+p.ProductNumber AS ItemID
,SUBSTRING(p.ProductName,0,100) as ItemName
,p.ProductName AS [Description]
,ManufacturerPriceListQty.Price As '+#PriceLevelAlias+'
,ManufacturerPriceListQty.Qty as OnHandQuantity
,ManufacturerPriceListQty.MultipleQty as OrderMinimumQuantity
,ManufacturerPriceListQty.MultipleQty as OrderMultipleQuantity
,Manufacturer.CompanyName AS CatalogName
,Manufacturer.CompanyName AS CatalogCode
,p.ProductNumber as UDF1
,CAST(p.ManufacturerID as varchar(2)) AS UDF2
,''%''+CAST(p.ProductID as varchar(10)) as UDF5
,CASE
WHEN P.Active =''1'' THEN ''FALSE''
ELSE ''TRUE''
END AS IsDeleted
,''' + #PriceLevelAlias + ''' AS PriceLevel
,ManufacturerPriceList.PriceListCode
,ManufacturerPriceListProduct.PriceListID
FROM ManufacturerPriceListProduct INNER JOIN
ManufacturerPriceList ON ManufacturerPriceListProduct.PriceListID = ManufacturerPriceList.PriceListID INNER JOIN
Manufacturer ON ManufacturerPriceList.ManufacturerID = Manufacturer.ManufacturerID INNER JOIN
ManufacturerPriceListQty ON ManufacturerPriceListProduct.PriceListProductID = ManufacturerPriceListQty.PriceListProductID INNER JOIN
Product p ON ManufacturerPriceListProduct.ProductID = p.ProductID
WHERE (Manufacturer.Active = 1)
AND p.Discontinued=0
AND PriceListCode
IN(SELECT * FROM dbo.Split(''' + #PriceListCodes + ''','',''))'
EXEC(#v_Qry)
END`

Using SQL variable in like statement

I have done much research on this but just cannot get it right. I am trying to query an audit trail using the below:
declare #batchid char (30)
select #batchid='13857584' --enter batch id here
declare #occurred int
select #occurred='5'
print 'Batch is in system, check MRN and encounter. User also noted below'
select a.encounter, a.mrn, a.facility, c.fullname, t.action_desc, a.occurred, a.remark
from audit..audit_trail a (nolock)
join cabinet..users c (nolock)
on a.userinstanceid=c.userinstanceid
join audit..action_table t (nolock)
on a.action=t.action
where a.REMARK like '%' + #batchid + '%'
and OCCURRED > GETDATE()-#occurred
order by a.occurred
for some reason it will never return the results i want (no results). But when i run it specifically for the batch id like below (instead of #batchid)
declare #batchid char (30)
select #batchid='13857584' --enter batch id here
declare #occurred int
select #occurred='5'
print 'Batch is in system, check MRN and encounter. User also noted below'
select a.encounter, a.mrn, a.facility, c.fullname, t.action_desc, a.occurred, a.remark
from audit..audit_trail a (nolock)
join cabinet..users c (nolock)
on a.userinstanceid=c.userinstanceid
join audit..action_table t (nolock)
on a.action=t.action
where a.REMARK like '%' + '13857584' + '%'
and OCCURRED > GETDATE()-#occurred
order by a.occurred
it works perfectly. I tried adding quotes after and before percentage signs but i just cant get it right. Any help appreciated. SQL 2008
You care declaring batchid as a char:
declare #batchid char (30)
select #batchid='13857584' --enter batch id here
In fact, the batchid is being set to something like:
'13857584______________________'
The underscores are intended to show the space character, not an actual underscore.
Try changing it to varchar():
declare #batchid varchar(30);
select #batchid = '13857584'; --enter batch id here

SQL update all negative numbers to null

I have a table in SQL Server with around of 300 columns. I want to create a stored procedure that replaces all the negative numbers with null.
The table has columns of type float, integer, nvarchar and so on.
I try to do it with T-SQL, but can't. Please could help me?.
Thanks.
EDIT:
I need a stored procedure that transforms all numeric columns to null if they are negative. The table is dynamic and may be increasing or decreasing the number of columns.
DECLARE #updateStatement AS VARCHAR(MAX)
SET #updateStatement = null
set #target_table =''
select * from systypes
select #updateStatement = COALESCE(#updateStatement+'UPDATE '+ #TARGET_TABLE+' SET '+c.name+ '= NULL WHERE' + c.name +' >0;' ,'UPDATE '+ #TARGET_TABLE +' SET '+c.name+ '= NULL WHERE' + c.name +' >0;' ) from syscolumns as c
inner join sysobjects as o on c.id= o.id
INNER JOIN systypes as t on c.xtype = t.xtype
where o.name= #TARGET_TABLE
AND T.name in('int','real','money','decimal')
select #updateStatement
--EXEC (#updateStatement)
You will need to add more to the where clause for T.name in () to hit all the data types you want. But this will query all the columns in 1 table #Target_Table then create update statements for each column in that table, if they are negative it will set the ALL ROWS for that column to null.
To make work uncomment out the EXEC(#UpdateStatement) THIS IS A REAL TERRIBLE IDEA, if you are dead set on doing this review your update statements
AND TAKE A BACKUP UP FIRST
EDIT*** THIS WILL NOT TAKE INTO ACCOUNT WEIRD FLOATING POINT MATH

Cannot specify an index or locking hint for a remote data source SQL Server 2005

I have this query which involves a table from another server:
select count(serialno), max(convert(varchar(10),Crtd_DateTime,101))
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
inner join [server_2].fdb.dbo.sns_in_out sio
on tsb.serialno = sio.lotsernbr and invtMult='-1' and RefNbr like 'I%'
where tmb.WO=34612
but this query is taking forever, and I cannot specify an index or locking hint for a remote data source, so I looked into the web and I found out that I can use this:
SELECT * FROM OpenQuery(server, 'Select * from sometable with (nolock)')
Which works fine, but as you can see I have a link between tsb.serialno and sio.lotsernbr, and when I place all that inside the '' like the following:
select serialno,
(SELECT *
FROM OpenQuery([server_2], 'select convert(varchar(10), Crtd_DateTime, 101)
from fdb.dbo.sns_in_out sio (nolock)
where (tsb.serialno = sio.lotsernbr
and invtMult=''-1'' and RefNbr like ''I%'')')) as crtDate
from tblSBox tsb (nolock)
inner join tblMBox tmb (nolock) on tsb.idMaster = tmb.idMaster
where tmb.WO=34612
I get this error:
[OLE/DB provider returned message: Deferred prepare could not be
completed.]
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "tsb.serialno" could not be bound.
Any idea of how to accomplish this?
If you want to run queries with (NOLOCK) on a remote server, create a stored procedure or view on the remote server and apply the locking hint there.
If you have no access to the remote server, you could pull the data first by executing something like this through a linked server (I'll assume your linked server is called server_2):
CREATE TABLE #loc (lotsernbr INT, dt DATETIME);
INSERT #loc
EXEC [server_2].fdb..sp_executesql 'SELECT lotsernbr, Crt_DateTime
FROM dbo.sns_in_out WITH (NOLOCK)
WHERE invtMult=''-1'' AND RefNbr LIKE ''I%'';';
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- much better than nolock on every table
SELECT tsb.serialno, crtDate = CONVERT(CHAR(10), loc.dt, 101)
FROM tblSBox AS tsb
INNER JOIN #loc AS loc
ON tsb.serialno = loc.lotsernbr
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612;
Now you can join against the local #temp table. The difference may be negligible but it may be significant. If this brings across a lot of rows and you only need a few, you may want to do it slightly differently: build your IN list dynamically and pass it to the other server, e.g.
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + ',' + CONVERT(VARCHAR(12), serialno)
FROM tblSBox AS tsb
INNER JOIN tblMBox AS tmb
ON tsb.idMaster = tmb.idMaster
WHERE tmb.WO = 34612
GROUP BY serialno; -- to avoid dupes
SET #sql = N'SELECT serialno = lotsernbr, crtDate = CONVERT(CHAR(10), Crt_Datetime, 101)
FROM fdb.dbo.sns_in_out WITH (NOLOCK)
WHERE lotsernbr IN (' + STUFF(#sql, 1, 1, N'') + ');'
-- now you don't need the join, since you are only outputting
-- the two columns:
EXEC [server_2].fdb..sp_executesql #sql;