SSDT - CROSS APPLY OPENJSON - json

Trying to write a stored procedure in SSDT like below:
CREATE PROCEDURE Response.TransformHotel
#RequestIDs Request.RequestIDs READONLY
AS
BEGIN
INSERT INTO response.Hotel
SELECT EventID,
JSON_VALUE(x.[value], '$.Id') AS HotelID,
JSON_VALUE(x.[value], '$.HasSpecialOffer') AS HasSpecialOffer,
JSON_VALUE(x.[value], '$.HasClosedUserGroupSpecialOffer') AS HasClosedUserGroupSpecialOffer,
JSON_VALUE(x.[value], '$.ReviewSummary.AverageScore') AS AvarageScore,
JSON_VALUE(x.[value], '$.PercentageScore') AS PercentageScore,
JSON_VALUE(x.[value], '$.NumberOfReviews') AS NumberOfReviews
FROM Search.[Event] E
INNER JOIN #RequestIDs R ON R.RequestID = E.EventID
CROSS APPLY OPENJSON(E.MessageEvent, '$.Response.SearchResults') AS x
END
But it is giving me error "SQL46010: Incorrect Syntax near E."
However, if I write this on SSMS and execute it I get no issues.
I tried with another stored procedure and it seems OPENJSON is not available in SSDT.
CREATE PROCEDURE Request.TestOpenJSON
AS
SELECT * FROM
OPENJSON( (SELECT E.MessageEvent FROM search.Event E WHERE E.EventID = 1))
Visual Studio Profesional 2015
Version 14.0.25123.00 Update 2
.NET Framework Version 4.6.010555
Project Settings:
Target Platform: SQL Server 2016
Has anyone got any ideas? Rather not refactor the query to resolve a SSDT problem if possible.
I have used JSON VALUE and JSON QUERY throughout the project and not had any issues.
Ideas passed around is to add this as a post deploy script which also isn't great as it's a workaround rather than a solution.

Maybe too late to answer but I had the same problem with the openjson instruction when I found this post, so here my results. If you restore a database from Sql Server 2012 (for example, without support of openjson) into a Sql Server 2016, the compatibility level remains in Sql Server 2012. You have to upgrade the database (not the engine) to level 130 or better:
ALTER DATABASE database_name
SET COMPATIBILITY_LEVEL = 130
https://msdn.microsoft.com/es-es/library/bb510680.aspx

Related

An item with the same key has already been added - SQL Server 2012 Subquery Issue

I am writing code within SQL server 2012 to transfer into the query designer of Report Builder 3.0.
My code works perfect within Management studio, and it works within the actualy query designer, but once I press Okay within the query designer, it throws me the error:
"Could not update a list of fields for the query. Verify that you can connect to the data source and that your query syntax is correct"
Under details:
"An item with the same key has already been added"
This is the code I am using:
Select *
from
(Select distinct srt.Name,
percentile_disc(.5) WITHIN GROUP(ORDER BY (sr.price)) OVER(PARTITION BY srt.Name) AS MedianSpend
from ServiceReq sr inner join ServiceReqTemplate srt
on srt.RecId = sr.SvcReqTmplLink_RecID Where Name like '%') medQuery
inner join
(select distinct srt.Name,
cast(sum(sr.price) as int) as AvgCost,cast(sum(sr.cost) as int) as
AvgTransCost,cast(avg(sr.TotalTimeSpent) as int) as TotalTimeSpent
from ServiceReq sr, ServiceReqTemplate srt
where sr.SvcReqTmplLink_RecID = srt.RecId
group by srt.Name) avgQuery
on medQuery.Name LIKE avgQuery.Name
I think that the problem is there would be two columns both called "Name" in one table, which is not allowed. I was thinking I could add another column in the same table, and call it "Name_2" and then copy and paste all the data from the "Name" table into "Name_2" and then use it. Would this be the easiest way of successfully implementing this code into Report Builder?
You add AS Name2 to the 2nd query and then call it after avgQuery at the end.

MySQL nested query won't run, runs on SQL Server

I'm running multiple queries on both MySQL and SQLServer (same queries on both servers, same db). Almost all of them run fine. I have a problem with this one:
SELECT
`Extent1`.`IdGosc`,
`Extent2`.`Imie`,
`Extent2`.`Nazwisko`
FROM `TGosc` AS `Extent1`
INNER JOIN `TOsoba` AS `Extent2` ON `Extent1`.`IdGosc` = `Extent2`.`IdOsoba`
WHERE EXISTS(
SELECT 1 AS `C1`
FROM (
SELECT `Extent3`.`IdRezerwacja`
FROM `TRezerwacja` AS `Extent3`
(here!) WHERE `Extent1`.`IdGosc` = `Extent3`.`IdGosc`) AS `Project1`
)
It runs on SQL Server just fine, returns correct results, but MySQL says:
Error Code: 1054. Unknown column 'Extent1.IdGosc' in 'where clause'.
Why so? :|
Are there any limitations about MySQL nested queries?
(Please don't offer queries that return the same and work, I can do that as well, but it's not my point)
I have seen this problem on MySQL.
SELECT `Extent1`.`IdGosc`, `Extent2`.`Imie`, `Extent2`.`Nazwisko`
FROM `TGosc` `Extent1` INNER JOIN
`TOsoba` `Extent2`
ON `Extent1`.`IdGosc` = `Extent2`.`IdOsoba`
WHERE EXISTS (SELECT `Extent3`.`IdRezerwacja`
FROM `TRezerwacja` AS `Extent3`
(here!) WHERE `Extent1`.`IdGosc` = `Extent3`.`IdGosc`
)
Fortunately, in this case, you can just eliminate the middle subquery.
I too have faced this sort of error in mysql.What I have done at tht tym is :
mysql remember only current table so try to do it may b it would work
replace
FROM `TRezerwacja` AS `Extent3
with
FROM `TRezerwacja` AS `Extent3`,`TGosc` AS `Extent1`
Ok. It turns out to be the problem with MySQL.
I'm using Entity Framework's query, that later turns into db specific SQL. I this case MySQL. So, the query in EF is:
var query3a = from TGosc gosc in context.TGosc
where gosc.TRezerwacja
.Any(x => x.TPlatnosc
.Any(y => y.Kwota > 100000))
select new { gosc.IdGosc, gosc.TOsoba.Imie, gosc.TOsoba.Nazwisko };
Now, the provider in my app is Connector NET 6.7.4. It includes MySQL.Data and MySQL.Data.Entities, both in version 6.7.4.
However, I also installed MySQL for Visual Studio 1.0.2 to be able to use more GUI than code in Visual Studio. But this thing comes with same dlls, just in different (older) versions 6.6.5. And these took precedence over the newer ones when application was running. (It's weird in the first place that in the same MySQL Installer there are two somehow conflicting versions of the same dlls.)
Anyway, I removed MySQL for Visual Studio 1.0.2, which left me with the newer dlls and see what happens to the very same LINQ to Entities query, when it's being translated to db sql:
--old 6.6.5
SELECT
Extent1.IdGosc,
Extent2.Imie,
Extent2.Nazwisko
FROM TGosc AS Extent1
INNER JOIN TOsoba AS Extent2 ON Extent1.IdGosc = Extent2.IdOsoba
WHERE EXISTS(
SELECT 1 AS C1
FROM (
SELECT Extent3.IdRezerwacja
FROM TRezerwacja AS Extent3
WHERE Extent1.IdGosc = Extent3.IdGosc) AS Project1
WHERE EXISTS(
SELECT 1 AS C1
FROM TPlatnosc AS Extent4
WHERE (Project1.IdRezerwacja = Extent4.IdRezerwacja)
AND (Extent4.Kwota > 100000)))
vs
-- new 6.7.4
SELECT
Extent1.IdGosc,
Extent2.Imie,
Extent2.Nazwisko
FROM TGosc AS Extent1
INNER JOIN TOsoba AS Extent2 ON Extent1.IdGosc = Extent2.IdOsoba
WHERE EXISTS(
SELECT 1 AS C1
FROM TRezerwacja AS Project1
WHERE EXISTS(
SELECT 1 AS C1
FROM TPlatnosc AS Extent4
WHERE (Project1.IdRezerwacja = Extent4.IdRezerwacja)
AND (Extent4.Kwota > 100000))
AND Extent1.IdGosc = Project1.IdGosc)
It's similar to what Gordon Linoff answered in this post. The middle subquery dissapears.
And of course the new query works fine!
Summing up, I guess the MySQL provider for .NET got better over these versions. I still have some queries that cause similar problems but now I think I know why that is - provider. I'm ok with that.
The annoying thing is that there are two different versions of dlls, one overriding another, in MySQL Installer. I'm using mysql-installer-community-5.6.13.0.

List of aggregate functions

Is there a way to fetch list of aggregate functions supported by a dbms using jdbc metadata or running any dbms specific query?
On SQL Server you can query XML which is in installation directory:
DECLARE #xml XML
SELECT #xml = x.y
FROM OPENROWSET( BULK 'C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\SqlToolsData\1033\SQLCommonObjects.xml', SINGLE_BLOB ) x(y)
;WITH XMLNAMESPACES( 'http://tempuri.org/SqlCommonObjects.xsd' AS ns )
SELECT
Category.Name.value('ns:DisplayName[1]', 'VARCHAR(MAX)') [Category],
[Function].Name.value('ns:Name[1]', 'VARCHAR(MAX)') [Function],
[Function].Name.query('for $p in ns:Parameters/ns:Parameter return
concat($p/ns:Name[1],",")').value('.', 'VARCHAR(MAX)') Parameters
FROM #xml.nodes('//ns:Category[ns:DisplayName="Aggregate Functions"]')
AS Category(Name)
CROSS APPLY Category.Name.nodes('ns:Objects/ns:Function') [Function](Name)
Where after BULK statement you should give your folder(difference mainly is Program Files" and "Program_Files(x86)" and SQL server version (100 is 2008 in example)
Your post has multiple DB tags, and each has system catalogs and/or an information schema that would let you know the list of procedures. Which table/view to query will differ from a DB engine to the next, however... (For instance, in Postgres you'd join pg_proc and pg_aggregate, since information_schema.routines won't tell you which procs are aggregates.)
It is usually safe to assume that typical aggregate functions (sum(), count(), avg()...) exist in all database implementations.
The only exception I'm aware of is Postgres, which does not support any()/some() due to ambiguity in the syntax:
SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;
There is nothing fullproof, since it is not part of the JDBC spec. If you don't know what database engine you are using at runtime, your best bet is to submit a test query to the database and check whether or not it failed before using any aggregate function that may not be supported.

Create View with Mutliple Tables in SQL Server 2008

I'm converting an app to use SQL Server 2008 that is currently using SQLite. How would I do the following view in SQL Server 2008? I can't seem to figure out the syntax for calling multiple tables:
CREATE VIEW new_mimetypes AS
SELECT
DISTINCT fd.mimetype AS 'newMimetype'
FROM
files_detail AS fd
WHERE
NOT EXISTS (
SELECT
m.mimetype
FROM
mimetypes AS m
WHERE
fd.mimetype = m.mimetype
)
[EDIT]
Nevermind. SQL Server Management Studio was complaining about syntax errors but it still took the SQL. That's what I get for thinking the IDE new what would work!
That syntax looks correct, are you getting an error?
I agree with #Adam Ruth that the syntax looks correct. I also wanted to add that you could use the "EXCEPT" operator as well to achieve the desired result:
CREATE VIEW [dbo].[new_mimetypes]
AS
SELECT mimetype As 'newMimetype' FROM files_detail
EXCEPT
SELECT mimetype FROM mimetypes

SubSonic 2.2 SqlQuery object generates very different sql for WHERE...IN statement for SQL Server 2008 and SQL Server 2005

Does anybody have an idea why SubSonic 2.2 SubSonic.SqlQuery object would be generating very different sql for the same C# code when running against SQL Server 2005 or SQL Server 2008?
I have a site that's been running for a while on SubSonic 2.2/SQL Server 2005. I just upgraded the DB to mssql 2008 and am encountering the following error:
SqlException (0x80131904): Incorrect syntax near the keyword 'AND'
I've dumped the SqlQuery.ToString() at the point of failure and noticed the following differences between running the exact same codebase on SQL Server 2005 and SQL Server 2008. Here is the source code:
SubSonic.SqlQuery q = new Select()
.From(Views.VwSearchIndexQuery2Mtx)
.Paged(pageNumber, maximumRows)
.Where(VwSearchIndexQuery2Mtx.Columns.SearchIndexQueryId)
.In(
new Select(SearchIndexQueryGroupMap.Columns.SearchIndexQueryId)
.From(Tables.SearchIndexQueryGroupMap)
.Where(SearchIndexQueryGroupMap.Columns.SearchIndexQueryGroupId)
.IsEqualTo(searchIndexQueryGroupId));
And the auto-generated sql for SQL Server 2005 is:
SELECT * FROM
(SELECT ROW_NUMBER() OVER ( ORDER BY CreatedOn DESC ) AS Row
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchTerms]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[DaysMonitored]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Incidents]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Relevance]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedOn]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedBy]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedOn]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedBy]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Deleted]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[LastUpdatedTime]
FROM [dbo].[Vw_SearchIndexQuery2_Mtx]
WHERE [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId]
FROM [dbo].[SearchIndexQueryGroup_Map]
WHERE [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId] = #SearchIndexQueryGroupId0 ) )
AS PagedResults WHERE Row >= 1 AND Row <= 20
The auto-generated sql for SQL Server 2008:
DECLARE #Page int
DECLARE #PageSize int
SET #Page = 1
SET #PageSize = 20
SET NOCOUNT ON
-- create a temp table to hold order ids
DECLARE #TempTable TABLE (IndexId int identity, _keyID Int)
-- insert the table ids and row numbers into the memory table
INSERT INTO #TempTable ( _keyID )
SELECT [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
FROM [dbo].[Vw_SearchIndexQuery2_Mtx]
WHERE [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId]
FROM [dbo].[SearchIndexQueryGroup_Map]
WHERE [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId]
= #SearchIndexQueryGroupId0
)
/* it's at this next AND where the error is thrown */
AND [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
IN (SELECT [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryId]
FROM [dbo].[SearchIndexQueryGroup_Map]
AND [dbo].[SearchIndexQueryGroup_Map].[SearchIndexQueryGroupId]
= #SearchIndexQueryGroupId0
)
ORDER BY CreatedOn DESC
-- select only those rows belonging to the proper page
SELECT [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchTerms]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[IndustryName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[DaysMonitored]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Incidents]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Relevance]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedOn]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[CreatedBy]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedOn]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[ModifiedBy]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[Deleted]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeId]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryTypeName]
, [dbo].[Vw_SearchIndexQuery2_Mtx].[LastUpdatedTime]
FROM [dbo].[Vw_SearchIndexQuery2_Mtx]
INNER JOIN #TempTable t ON [dbo].[Vw_SearchIndexQuery2_Mtx].[SearchIndexQueryId] = t._keyID
WHERE t.IndexId BETWEEN ((#Page - 1) * #PageSize + 1) AND (#Page * #PageSize)
I know why the error is happening - the sql is invalid by the AND that I've commented above. I just can't figure out why SubSonic is generating invalid SQL after it worked on SQL Server 2008. You'll see that for SQL Server 2008 it uses a temp table and it also looks like it's repeating the WHERE...IN sub-query. I thought maybe it was the ISO Compatibility Level since the upgraded DB was set for 100. So I've tested with setting it to both 90 & 80 and SubSonic generates the same sql as in each case. (And BTW, the code generated for SQL Server 2005 which uses "select rownumber() over... as row" executes fine against SQL Server 2008.)
Does anyone have any ideas why this is happening and how to track it down?
Many thanks,
Terry
This may have been fixed already in the source? I suggest you try the most recent source from github to see if the problem has been addressed.
Basically, it's as you said -- the 2005 generator overrides the BuildPagedSelectStatement() method provided by ANSISqlGenerator. The 2008 generator inherits from 2005, so it should use the same paging method as 2005.
This can be seen by comparing these two files:
I believe you would also see the behavior you're describing on a SQL 2000 database since it doesn't override the ANSISqlGenerator.BuildPagedSelectStatement() method.
Also, I don't think compatability level is used to determine the SQL generator:
public static bool IsSql2008(DataProvider provider)
{
return provider.DatabaseVersion.IndexOf("2008 - 10.") > -1 ||
provider.DatabaseVersion.IndexOf("2008 (RTM) - 10.") > -1;
}
And, assuming the ANSI generator is what's actually being used, the problem with the AND may be caused by this line in BuildPagedSqlStatement():
//have to doctor the wheres, since we're using a WHERE in the paging
//bits. So change all "WHERE" to "AND"
string tweakedWheres = wheres.Replace("WHERE", "AND");
It needs to be a little smarter than that, although the point you raise about the duplicated clause also needs to be addressed.
Just encountered this error and am very glad I found this page, because I had no idea why it was happening.
It seems that running SQL Server 2008 SP1 causes IsSql2008 to be FALSE. As the returned DatabaseVersion (on my machine) is returned as "Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64) ..." which doesn't meet the criteria of the IsSql2008 function.
Looks like this still hasn't been addressed on the github codebase?
Why not have something simpler like
if (provider.DatabaseVersion.Contains("SQL Server 2008"))
This issue is documented here. I just forked and committed the fix so it should be included shortly.