I have come to understand that some versions of Microsoft OLE DB Provider for SQL Server (mostly on Windows XP) do not support WITH
statement. So, I decided to move my SQL statement into a table-valued function, and call it from my application. Now, I'm stuck. How should I use the INSERT INTO
statement with WITH
? Here's the code I have come with so far, but SQL Server doesn't like it... :-(
CREATE FUNCTION GetDistributionTable ( @IntID int, @TestID int, @DateFrom datetime, @DateTo datetime ) RETURNS @Table_Var TABLE ( [Count] int, Result float ) AS BEGIN INSERT INTO @Table_Var ([Count], Result) WITH T(Result) AS (SELECT ROUND(Result - AVG(Result) OVER(), 1) FROM RawResults WHERE IntID = @IntID AND DBTestID = @TestID AND Time >= @DateFrom AND Time <= @DateTo) SELECT COUNT(*) AS [Count], Result FROM T GROUP BY Result RETURN END GO
You can only use a CTE within the context of DML language (SELECT, INSERT, UPDATE, DELETE, MERGE).
CTE was introduced in SQL Server 2005, the common table expression (CTE) is a temporary named result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement. You can also use a CTE in a CREATE a view, as part of the view's SELECT query.
You can also use CTE to insert data into the SQL table. The CTE query definition includes the required data that you can fetch from existing tables using joins.
Syntax for the CTE in table valued function would be:
CREATE FUNCTION GetDistributionTable ( @IntID int, @TestID int, @DateFrom datetime, @DateTo datetime ) RETURNS TABLE AS RETURN ( WITH cte AS ( SELECT ROUND(Result - AVG(Result) OVER(), 1) Result FROM RawResults WHERE IntID = @IntID AND DBTestID = @TestID AND Time >= @DateFrom AND Time <= @DateTo ) SELECT COUNT(*) AS [Count], Result FROM cte GROUP BY Result ) GO
If possible, you can also omit the CTE (WITH
statement), and instead create an inline table valued function that uses subquery:
CREATE FUNCTION GetDistributionTable ( @IntID int, @TestID int, @DateFrom datetime, @DateTo datetime ) RETURNS TABLE AS RETURN ( SELECT COUNT(*) AS [Count], Result FROM ( SELECT ROUND(Result - AVG(Result) OVER(), 1) Result FROM RawResults WHERE IntID = @IntID AND DBTestID = @TestID AND Time >= @DateFrom AND Time <= @DateTo ) t GROUP BY Result ) GO
Your example seems to be using a multi-statement TVF (insert and select), when you have a choice try using the inline TVF because the multi-statement TVF can prevent query optimizer in choosing a better execution plan (performance difference explained here)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With