This query (or rather one similar to it) is in a codebase we have already deployed.
var timeblocks = from tb in DB.TimeBlocks
where tb.StartDate.Date.AddDays(1) <= DateTime.Today
select tb.Id;
DB is a datacontext that connects to the database. TimeBlocks is a fairly simple table, StartDate is a DateTime column.
Currently the database is hosted on a Sql Server 2005 Installation, but we are in the process of upgrading to a Sql Server 2008 Installation.
The query currently exectutes without problems.
If we change the connection string to point at a copy of the same database running on Sql Server 2008 (with the compatability level set for 2005) the query fails with the SqlException:
"The datepart millisecond is not supported by date function dateadd for data type date."
This seems to be due to the different sql emitted by Linq to SQL when it connects to the 2008db (I assume this is because it uses Sql2008Provider instead of the Sql2005Provider).
The 2005 Provider produces good SQL:
SELECT [t0].[Id]
FROM [dbo].[TimeBlock] AS [t0]
WHERE DATEADD(ms, (CONVERT(BigInt,#p0 * 86400000)) % 86400000, DATEADD(day, (CONVERT(BigInt,#p0 * 86400000)) /
86400000, DATEADD(HOUR, -DATEPART(HOUR, [t0].[StartDate]), DATEADD(MINUTE, -DATEPART(MINUTE,
[t0].[StartDate]), DATEADD(SECOND, -DATEPART(SECOND, [t0].[StartDate]), DATEADD(MILLISECOND,
-DATEPART(MILLISECOND, [t0].[StartDate]), [t0].[StartDate])))))) <= #p1
which successfully executes the query. However the sql emitted by the Sql2008Provider:
SELECT [t0].[Id]
FROM [dbo].[TimeBlock] AS [t0]
WHERE DATEADD(ms, (CONVERT(BigInt,#p0 * 86400000)) % 86400000, DATEADD(day, (CONVERT(BigInt,#p0 * 86400000)) /
86400000, CONVERT(DATE, [t0].[StartDate]))) <= #p1
Contains the erroneous sql that causes the exception.
Am I right in thinking that the it is the Sql provider that is causing this problem?
Is there a way we can get round this problem by forcing the DataContext to use the Sql2005Provider for this db?
Thanks for any help you can give us!
It seems to me you found a bug in LINQ to SQL. You should report it to Microsoft. You can do that here: http://connect.microsoft.com/
Related
I'm struggling to create MariaDB SQL commands which will produce the same output as these three queries (below) which I'm currently using with an MS Access database. My Excel VBA script calls the third SQL query command below (Hours to Heat Elecric WH) with only this SQL command, where the date value is substituted dynamically. For the purposes of this question that command would look like this:
SELECT ElectricWH_Data.*
FROM ElectricWH_Data
WHERE (ElectricWH_Data.Date_Reading) > #06/01/19#;
This is an abstract of the resulting table:
Date_Time Date Time Max WH Out Min WH Out
6/27/18 0:52 06/27/18 00.52 60.38 43.56
6/28/18 0:52 06/28/18 00.52 60.50 44.44
6/29/18 0:32 06/29/18 00.32 60.13 45.38
6/30/18 0:32 06/30/18 00.32 60.19 47.13
7/1/18 0:12 07/01/18 00.12 60.50 47.56
7/2/18 0:42 07/02/18 00.42 60.44 44.94
7/3/18 0:42 07/03/18 00.42 60.38 46.88
I would like to duplicate this process but using a MariaDB database and SQL commands. Can you assist?
By the way, I am aware that dates and date formats are handled differently in MariaDB.
Below are the SQL queries from the MS Access database.
GetTemDataByDay:
SELECT
Min(PiSolarWH.Electric_WH_Out) AS MinOfElectric_WH_Out,
Max(PiSolarWH.Electric_WH_Out) AS MaxOfElectric_WH_Out,
Format(PiSolarWH.Date_Reading,'mm/dd/yy') AS TheDay
FROM
PiSolarWH
GROUP BY
Format(PiSolarWH.Date_Reading,'mm/dd/yy');
ElectricWHData:
SELECT
PiSolarWH.Date_Reading,
Format([PiSolarWH.Date_Reading],'mm/dd/yy') AS TheDate,
Format([Date_Reading],'hh.mm') AS DayTime,
GetTempDataByDay.MaxOfElectric_WH_Out AS Expr1,
GetTempDataByDay.MinOfElectric_WH_Out AS Expr2
FROM
GetTempDataByDay, PiSolarWH
WHERE
Format([PiSolarWH.Date_Reading],'mm/dd/yy') = [GetTempDataByDay].[TheDay]
AND GetTempDataByDay.MaxOfElectric_WH_Out = [PiSolarWH].[Electric_WH_Out];
Hours to Heat Elecric WH:
SELECT
PiSolarWH.Date_Reading,
Format([Date_Reading],'hh.mm') AS DayTime,
GetTempDataByDay.MaxOfElectric_WH_Out,
PiSolarWH.Electric_WH_Out,
Format([PiSolarWH.Date_Reading],'mm/dd/yy') AS Expr1
FROM
GetTempDataByDay,
PiSolarWH
WHERE
GetTempDataByDay.MaxOfElectric_WH_Out = [PiSolarWH].[Electric_WH_Out]
AND Format([PiSolarWH.Date_Reading],'mm/dd/yy') = [GetTempDataByDay].[TheDay];
OK, I figured it out! MariaDB's stored VIEWS work like MS Access Stored Queries. I was able to add the three MS Access queries (of course with modified syntax) to the database as stored VIEWS. The work exacgtly like those in MS Access. Here is one example:
CREATE VIEW GetTempDataByDay AS
SELECT
date_reading,
Min(temps.Electric_WH_Out) AS MinOfElectric_WH_Out,
Max(temps.Electric_WH_Out) AS MaxOfElectric_WH_Out,
date(temps.Date_Reading) AS TheDay
FROM
temps
GROUP BY
date(temps.Date_Reading);
Which is then used in the other two VIEWS which I created to duplicate the MS Access stored queries.
Thanks for your time....RDK
I've written a common table expression to return hierarchical information and it seems to work without issue if I hard code a value into the WHERE statement. If I use a variable (even if the variable contains the same information as the hard coded value), I get the error The maximum recursion 100 has been exhausted before statement completion.
This is easier shown with a simple example (note, I haven't included the actual code for the CTE just to keep things clearer. If you think it's useful, I can certainly add it).
This Works
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = 'ABCDE';
This throws the Max Recursion Error
DECLARE #part CHAR(25);
SET #part = 'ABCDE'
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = #part;
Am I missing something silly? Or does the SQL engine handle hardcoded values and parameter values differently in this type of scenario?
Kindly put semicolon at the end of your variable assignment statement
SET #part ='ABCDE';
Your SELECT statement is written incorrectly: the SQL Server Query Optimizer is able to optimize away the potential cycle if fed the literal string, but not when it's fed a variable, which uses the plan that developed from the statistics.
SQL Server 2016 improved on the Query Optimizer, so if you could migrate your DB to SQL Server 2016 or newer, either with the DB compatibility level set to 130 or higher (for SQL Server 2016 and up), or have it kept at 100 (for SQL Server 2008) but with OPTION (USE HINT ('ENABLE_QUERY_OPTIMIZER_HOTFIXES')) added to the bottom of your SELECT statement, you should get the desired result without the max recursion error.
If you are stuck on SQL Server 2008, you could also add OPTION (RECOMPILE) to the bottom of your SELECT statement to create an ad hoc query plan that would be similar to the one that worked correctly.
Im trying to Establish a One Direction Sync from a specific query'd recordset from MSSQL (express 2008) to Mysql. Here is that query.
SELECT [datafk]
,[datahistorypk]
,[date]
,[displayText]
FROM [FCentral].[dbo].[DataHistory]
WHERE [sampleNr] =
(SELECT MAX (sampleNr) FROM [FCentral].[dbo].[DataHistory])
This results in a Multiple results. I need to insert each of those results into my "Linked Server" remotely connected MySQL DB Table.
This code works from SSMS and does insert into my MySQL DB.
EXEC (' INSERT INTO `farms`.`CCData` (
`datafk` ,`datahistorypk` ,`date` ,`displayText` )
VALUES ("222", "13", "2017-10-19 14:25:05", "TEST"); ')
at BPF_REMOTE
Ultimately i will need to schedule this query to run automatically, It would be nice if it could run if a change was detected in the MSSQL table but that may be outside of my abilities.
I feel like im close, im just struggling to get the syntax right to convert from MSSQL to MySQL. Can anyone either point to a good example or help me with this query?
Set up a linked server in SQL Server and just do a regular insert:
INSERT INTO BPF_REMOTE.farms.CCData(datafk, datahistorypk, date, displayText)
SELECT [datafk], [datahistorypk], [date], [displayText]
FROM [FCentral].[dbo].[DataHistory]
WHERE [sampleNr] = (SELECT MAX (sampleNr) FROM [FCentral].[dbo].[DataHistory]);
Currently, the jTDS JDBC driver (1.2.5) against Microsoft SQL Server 2008 appears to incorrectly report the data type for DATE columns as NVARCHAR.
It probably behaves the same for both earlier versions of jTDS and SQL Server (2005, 2000)
Are there any workarounds for this that don't require switching to a different driver (for example Microsoft's own driver) or patching the jTDS driver?
Also I would like to avoid having to perform queries against the data dictionary (INFORMATION_SCHEMA.COLUMNS view, etc.) to look up the data type information (and possibly cross-referencing against the output of "exec sp_datatype_info" in order to retrieve the SQL data types)
A quick perusal of the jTDS outstanding bugs doesn't indicate whether this will be fixed or not.
An answer to this question: JDBC - JTDS bug ? For columns of type date and time(x) seems to indicate that this doesn't occur in SQL Server 2005.
Thanks in advance.
I found a solution with the condition
metaData.getColumnType(columnNumber) == 12
if this condition is satisfied, execute the query
SELECT System_Type_Id FROM Sys.Columns WHERE Name = [column name] AND Object_Id = (SELECT Object_Id FROM Sys.Tables WHERE Name = [table name])
for smalldatetime it will return 58
and for datetime it will return 61.
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.