sql server query is not working in delphi [closed] - sql-server

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
i have this code:
DECLARE #top VARCHAR(2000)
DECLARE #sql VARCHAR(4000)
SELECT #top =STUFF((SELECT DISTINCT
'],['+ ltrim([itemID])
FROM ARInvDet
ORDER BY '],['+ ltrim([itemID])
FOR XML PATH('')
), 1, 2, '')+']'
SET #sql ='
SELECT ItemID,Quantity,Price FROM(
select * From (
select
a.CustomerID as [CustomerID],
a.DateFinalize as [Date],
ad.Quantity as [Quantity],
ad.UnitPrice as [Price],
i.ItemTypeID as [ItemTypeID],
i.ItemID as [ItemID]
from ARInvDMS a
inner join ARInvDet ad on a.ARInvoiceID = ad.ARInvoiceID
inner join item i on ad.ItemID = i.ItemID
WHERE CustomerID = 10056 and a.[DateFinalize] = CONVERT(DATETIME,''2/28/2014'', 102)
and i.[ItemTypeID] = 1
) src
PIVOT
(
SUM(Quantity)
FOR [ItemID] in ('+#top+')
) as pvt
) as src2
UNPIVOT
(
Quantity FOR ItemID in ('+#top+')
) as unpvt
'
execute(#sql)
the error is Incorrect Syntax near '2': it from the WHERE statement.. but i tried to run this code in sql server 2008 r2..and its working fine.. but when i used this in my delphi program.. this error appears.. please help.

The problem is with the doubled quotes around the date.
If you run this query in SQL Server exactly as you show it here, it will choke on
''2/28/2014''
because it needs to be surrounded with single quotes.
'2/28/2014'
Now let's talk about how you're going to run this query from Delphi.
Are you putting this text into a query object at design time?
Or are you using it as a string constant within your program?
If you're just setting the SQL text at design time, you can enter the raw query directly as is, once you've corrected for the doubled quotes.
If you're using a string constant, you need to double every single quote:
const
sqlSCRIPTXXX =
'DECLARE #top VARCHAR(2000)'
+ #13#10'DECLARE #sql VARCHAR(4000)'
+ #13#10'SELECT #top =STUFF((SELECT DISTINCT'
+ #13#10' ''],[''+ ltrim([itemID])'
+ #13#10' FROM ARInvDet '
+ #13#10' ORDER BY ''],[''+ ltrim([itemID])'
+ #13#10' FOR XML PATH('''')'
+ #13#10' ), 1, 2, '''')+'']'''
+ #13#10''
+ #13#10''
+ #13#10'SET #sql ='''
+ #13#10'SELECT ItemID,Quantity,Price FROM('
+ #13#10'select * From ('
+ #13#10'select '
+ #13#10'a.CustomerID as [CustomerID],'
+ #13#10'a.DateFinalize as [Date],'
+ #13#10'ad.Quantity as [Quantity],'
+ #13#10'ad.UnitPrice as [Price],'
+ #13#10'i.ItemTypeID as [ItemTypeID],'
+ #13#10'i.ItemID as [ItemID]'
+ #13#10'from ARInvDMS a '
+ #13#10'inner join ARInvDet ad on a.ARInvoiceID = ad.ARInvoiceID'
+ #13#10'inner join item i on ad.ItemID = i.ItemID'
+ #13#10'WHERE CustomerID = 10056 and a.[DateFinalize] = CONVERT(DATETIME,''2/28/2014'', 102)'
+ #13#10'and i.[ItemTypeID] = 1'
+ #13#10') src'
+ #13#10''
+ #13#10'PIVOT '
+ #13#10'('
+ #13#10' SUM(Quantity)'
+ #13#10' FOR [ItemID] in (''+#top+'')'
+ #13#10''
+ #13#10') as pvt'
+ #13#10') as src2'
+ #13#10'UNPIVOT'
+ #13#10'('
+ #13#10' Quantity FOR ItemID in (''+#top+'')'
+ #13#10') as unpvt'
+ #13#10''
+ #13#10''''
+ #13#10''
+ #13#10'execute(#sql)';
I have a utility that I wrote just to do these conversions. The code above is the output of that utility.
So, in this case, the quotes around the date are doubled, and so are all the other quotes.

Related

Replace “<” and “>”and "<\" with “<” ,“>” and </ in sql server

I know that Replace < and > with < and > in sql server has been asked at
Replace “<” and “>” with “<” and “>” in sql server
but I need to expand upon it. I am trying to create formatted HTML code from a MS 2016 SQL server.
What I have is:
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</' + AU1.Format + '>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH ('')
), 3, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
SELECT #json
And what I get back is:
Name DG, Name K, Name A, Chen FK, Song X, Pirun M, Santiago PM, Kim-Kiselak C, Platt JT, Lee E, Hodges E, <b>Rosebrock AP</b>, Bronson RT, Socci ND, Hannon GJ, Jacks T, Varmus H Journal Name
If I try to put TYPE into the
FOR XML PATH(''), TYPE
I get an error saying:
Argument data type xml is invalid for argument 1 of substring function.
I've tried to add REPLACE
replace(CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END, '<', '<')
But then I get an error
The xml data type cannot be selected as DISTINCT because it is not comparable.
The best that I can come up with is:
SET #json = replace(#json, '<\', '<')
SET #json = replace(#json, '<', '<')
SET #json = replace(#json, '>', '>')
Just before the final SELECT #json.
I will have over a 1000 records that I need to pull. Do I need to do this is steps?
Based upon TT code I changed mine to
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH (''),TYPE).value('.[1]','NVARCHAR(MAX)'
), 1, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
And that woks fine. but see comment below
As far as I can tell you are on the right track with FOR XML PATH(''), TYPE. It's just that you then have an XML text value which you need to convert to a string (i.e. of type [N]VARCHAR(X)). This can be done with the XML value() method.
An example (fiddle):
CREATE TABLE t(s NVARCHAR(16));
INSERT INTO t(s)VALUES(N'1'),(N'2'),(N'3'),(N'4'),(N'5'),(N'6');
SELECT
(
SELECT N'<b>'+s+N'</b>'
FROM t
FOR XML PATH(''),TYPE
).value('.[1]','NVARCHAR(MAX)');
results in
<b>1</b><b>2</b><b>3</b><b>4</b><b>5</b><b>6</b>

Paginating a parent in SQL Server on a parent/child query

(SQL Server 2012 - Web Edition)
I have a parent/child (one to many) relationship in a query like so:
SELECT a.a, a.b, b.c
FROM tablea INNER JOIN
tableb ON b.pk = a.fk
I have a huge pagination query that encompasses this using the standard (psuedo-code):
WITH C as (SELECT top(#perpage*#pagenum) rowID = row_number() OVER (somefield)),
SELECT c.* FROM C (query) WHERE DT_RowId > (#pagenum-1)*#perpage
The question I have is in this scenario is it possible to paginate off the parent table (a), instead of the entire query? Can I modify my pagination query (not the sql that pulls the query itself) so that when I ask for 10 rows, it gives me 10 rows from the parent, with 'x' number of children attached?
I know I'm not giving the bigger picture here, but the bigger picture is ugly. If need be, we can go there, but it's out there. Here's a small taste of where we're going with this:
IF UPPER(LEFT(#rSQL, 6)) = 'SELECT'
BEGIN
SET #rSQL = 'SELECT * FROM (' + #rSQL + ')' + ' as rTBL';
SET #rSQL = RIGHT(#rSQL, LEN(#rSQL)-7);
IF (LEN(LTRIM(#search)) > 0)
BEGIN
SET #rPaging =
'IF (#schemaonly=1) SET FMTONLY ON;
SELECT #ttlrows = COUNT(*) FROM (SELECT ' + #rSQL + #rWhere + ') AS TBL;
WITH C as (select top(#perpage*#pagenum) DT_RowId = ROW_NUMBER() OVER (' + #rOrder + '), ';
SET #rPaging = #rPaging + #rSQL + #rWhere + ')
SELECT C.*' + #rcols + ', (#perpage-1) * #pagenum as pagenum, #ttlrows as ct, CEILING(#ttlrows / CAST(#perpage AS FLOAT)) as pages
FROM C '+ #query + ' WHERE DT_RowId > (#pagenum-1) * #perpage ';
END
ELSE
BEGIN
SET #rPaging =
'IF (#schemaonly=1) SET FMTONLY ON;
SELECT #ttlrows = COUNT(*) FROM (' + #oSQL + ') AS SUBQUERY;
WITH C as (select top(#perpage*#pagenum) DT_RowId = ROW_NUMBER() OVER (' + #rOrder + '), ';
SET #rPaging = #rPaging + #rSQL + ')
SELECT C.*' + #rcols + ',(#perpage-1) * #pagenum as pagenum, #ttlrows as ct, CEILING(#ttlrows / CAST(#perpage AS FLOAT)) as pages
FROM C '+ #query + ' WHERE DT_RowId > (#pagenum-1) * #perpage ';
END
PRINT #rPaging;
EXECUTE SP_EXECUTESQL #rPaging, #parms, #ttlrows out, #schemaonly, #perpage, #pagenum, #fksiteID, #filter1, #filter2, #filter3, #filter4, #intfilter1, #intfilter2, #intfilter3, #intfilter4, #datefilter1, #datefilter2, #search;
SET FMTONLY OFF;
END
ELSE
BEGIN
SET #rSQL = LTRIM(REPLACE(UPPER(#rSQL), 'EXEC',''));
EXECUTE SP_EXECUTESQL #rSQL, #parms, #ttlrows out, #schemaonly, #perpage, #pagenum, #fksiteID, #filter1, #filter2, #filter3, #filter4, #intfilter1, #intfilter2, #intfilter3, #intfilter4, #datefilter1, #datefilter2;
END
You could do the pagination in a CTE that only gets the parent rows, and then join the child rows in a subsequent CTE or in the main query.
Due to the dynamic way you are using this, this might have to involve building your pagination query from the same building blocks you use to build #query. Without seeing the code that builds #query I can't be much more specific than that.
You could add
,DENSE_RANK() OVER (ORDER BY table_a.primary_key)
This would indirectly provide the same result as
,ROW_NUMBER() OVER(ORDER BY table_a.primary_key)
but the former would be on the final result set instead going back to table a for the latter code snippet.
But please be aware of the disadvantage: any additional ranking function will force an additional sort operation on the result set! This might significantly influence the query performance. If this is the case in your scenario, I'd recommend to follow Tab Allemans solution and use a cte.

Generate XML from SQL issue

I need to generate XML in the following format :
I haven't gone too far with the xml part of the task as I encountered following situation, you can tell that this obviously was not my intention.
How can I handle this properly considering that BBAN and IBAN need to be inside AccountNoas well as that I want it formatted according to the first picture.
The complete query along with my fair attempt of generating xml looks like this:
DECLARE #AccountType NVARCHAR(3);
DECLARE #kodBanke NVARCHAR(3);
SET #AccountType = 'T';
SET #kodBanke = ( SELECT vrednost FROM dbini WHERE IDENT = 'KOD' AND SECTION = 'PP' );
WITH Ent_Posta
AS
(
SELECT e.naziv,p.posta,e.sifra
FROM entitet AS e
INNER JOIN poste AS p ON e.sifra = p.entitet
)
SELECT (
SELECT
[dbo].[brojracuna](#kodBanke,i.partija) AS 'BBAN',
[dbo].[GENERATEIBAN](i.partija) AS 'IBAN'
FOR XML PATH('AccountNo'), ELEMENTS, ROOT('Account')
),
#accountType AS 'AccountType',
(a.ime + ' ( ' + a.roditel + ' ) ' + a.prezime) AS 'Name',
a.embg AS 'UID',
CASE status
WHEN 2 THEN 'A'
WHEN 4 THEN 'B'
WHEN 8 THEN 'U'
END AS 'Status',
c.sifra AS 'Territory',
#kodBanke as 'ID_Bank',
REPLACE(CONVERT(VARCHAR(10), i.DOTVaRANJE, 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(s, i.DOTVaRANJE)),2) AS OpeningDate,
REPLACE(CONVERT(VARCHAR(10),'2006.09.28 ', 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, '2006.09.28' )), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, '2006.09.28 ')), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(s,'2006.09.28 ')),2) AS ClosingDate
FROM adresar AS a
INNER JOIN istdden AS i
ON a.embg = i.embg
INNER JOIN Ent_Posta as c
ON a.postbroj = c.posta
FOR XML PATH ('Account'), ROOT('Accounts');
Upon removal of this part I get...
<Accounts>
<Account>
<BBAN>5710543102313248</BBAN>
<IBAN>BA39531231634039248</IBAN>
<AccountType>T</AccountType>
<Name>DARKO ( DRAGAN ) TESIC</Name>
<UID>0000005467234</UID>
<Status>A</Status>
<Territory>1</Territory>
<ID_Bank>571</ID_Bank>
<OpeningDate>20081205-000000</OpeningDate>
<ClosingDate>20060928-000000</ClosingDate>
</Account>
... but now AccountNO is missing.
Your question is not all clear, but - if I get this correctly - you are fighting with 1:1 values, but within some deeper nesting.
You can use an XPath-like expression within [] in connection with FOR XML PATH. Check this out:
SELECT 'blah' AS FirstNode
,'blub' AS [SecondNode/OneDeeper]
,'blib' AS [SecondNode/OneMore]
,'ballaballa' AS [ThirdNode]
FOR XML PATH('row'),ROOT('root');
the resutl (look especially at <SecondNode>:
<root>
<row>
<FirstNode>blah</FirstNode>
<SecondNode>
<OneDeeper>blub</OneDeeper>
<OneMore>blib</OneMore>
</SecondNode>
<ThirdNode>ballaballa</ThirdNode>
</row>
</root>
If this is not what you need, please tag with the actual RDBMS (product and version) and please read How to ask a good SQL question and How to create a MCVE
For your issue it might be enough to use AS [AccountNo/IBAN] in your query.

SQL Server build dynamic sql

I have a temp table called #temp, and I need to get all the CDate column from that table, to build a string.
The CDate list in that table is (20171209, 20171210....20171223)
I expected to see
'A.[20171209] as [20171209], A.[20171210] as [20171210],
A.[20171211] as [20171211], A.[20171212] as [20171212],
A.[20171213] as [20171213], A.[20171214] as [20171214],
A.[20171215] as [20171215], A.[20171216] as [20171216],
A.[20171217] as [20171217], A.[20171218] as [20171218],
A.[20171219] as [20171219], A.[20171220] as [20171220],
A.[20171221] as [20171221], A.[20171222] as [20171222],
A.[20171223] as [20171223], '
however the result I got is missing the first date , ie 'A.[20171209] as [20171209]'
Here is my code:
SELECT
#col2 = ISNULL(#col2 + 'A.' + QUOTENAME(CDate) + ' as ' + QUOTENAME(CDate) + ', ' , '')
FROM
(SELECT DISTINCT CDate FROM #temp) AS tmp;
Your current approach will not work in some cases, it is an undocumented feature, always use For Xml path to concatenating the rows into csv.
SET #col2 = stuff((SELECT ', A.' + Quotename(CDate) + ' as '
+ Quotename(CDate)
FROM (SELECT DISTINCT CDate
FROM #temp) a
FOR xml path('')),1,1,'')

SQL Server Query to return all Stored Procedures, Functions, Tables and Views with their Parameters / Columns

I need a SQL Server query (preferably for SQL Server 2012+) that will return a list of all non-system stored procedures, functions, tables and views and that will also return a simple list of all their associated parameters / column names.
The simple list should be something like a CSV, although JSON is preferred.
The objective is to be able to run the query and get a list of entities with enough information to be able to construct further queries / execute statements to a basic level.
I'm answering my own question. I found a lot of the answers related to much older versions of SQL Server. But I also found a lot of the answers were fragmentary and I wanted something that was a bit 'better' (hopefully) as a starting point.
Here it is:
SELECT DISTINCT
QUOTENAME(isc2.TABLE_SCHEMA) + '.' + QUOTENAME(isc2.TABLE_NAME) AS sqlEntName
, 'TV' AS sqlEntType
, '{' + SUBSTRING((
SELECT ',\"' + isc1.COLUMN_NAME + '\":\"' + isc1.DATA_TYPE + '\" '
FROM INFORMATION_SCHEMA.COLUMNS isc1
WHERE QUOTENAME(isc1.TABLE_SCHEMA) + '.' + QUOTENAME(isc1.TABLE_NAME)
= QUOTENAME(isc2.TABLE_SCHEMA) + '.' + QUOTENAME(isc2.TABLE_NAME)
ORDER BY ORDINAL_POSITION
FOR XML PATH ('')
), 2, 1024) + '}' AS sqlClmPrmNames
FROM INFORMATION_SCHEMA.COLUMNS isc2
UNION
SELECT DISTINCT
QUOTENAME(isp2.SPECIFIC_SCHEMA) + '.' + QUOTENAME(isp2.SPECIFIC_NAME) AS sqlEntName
, 'SF' AS sqlEntType
, ISNULL('{' + SUBSTRING((
SELECT ',\"' + isp1.PARAMETER_NAME + '\":\"' + isp1.DATA_TYPE + '\" '
FROM INFORMATION_SCHEMA.PARAMETERS isp1
WHERE QUOTENAME(isp1.SPECIFIC_SCHEMA) + '.' + QUOTENAME(isp1.SPECIFIC_NAME) NOT IN
(SELECT QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name)
FROM sys.all_objects
WHERE is_ms_shipped = 1 AND [type] IN ('P'))
AND QUOTENAME(isp1.SPECIFIC_SCHEMA) + '.' + QUOTENAME(isp1.SPECIFIC_NAME)
= QUOTENAME(isp2.SPECIFIC_SCHEMA) + '.' + QUOTENAME(isp2.SPECIFIC_NAME)
ORDER BY QUOTENAME(isp1.SPECIFIC_SCHEMA) + '.' + QUOTENAME(isp1.SPECIFIC_NAME)
, isp1.ORDINAL_POSITION
FOR XML PATH ('')
), 2, 1024) + '}', '{}') AS sqlClmPrmNames
FROM INFORMATION_SCHEMA.PARAMETERS isp2
WHERE isp2.SPECIFIC_NAME NOT LIKE '%diagram%' -- You may need to remove this final filter clause
This will yield three columns, the first with the name of the entity, the second with the 'type' (either 'TV' for table or view, or 'SF' for stored procedure or function), and the third with a JSON-esque list of column names / parameter names.

Resources