What does "a" do at the end of a sql statement? - sql-server

I have a code here in the screenshot. At the end of the code you see a "a"
When i try to remove the "a" and run the code, it fails but it works with the "a"
what is the significance of this ?

Edit: Question was originally tagged MySQL. However, the explanation below should still apply for all the major RDBMS.
It is an Aliasname for the Derived Table. A Derived table is basically a sub-select query. In MySQL, every Derived Table should have its own Alias, so that outer Select queries can refer to the columns/expressions from the Derived Table. Without a table name/alias, MySQL cannot determine the origin of a column value unambiguously.
From Docs:
The [AS] tbl_name clause is mandatory because every table in a FROM
clause must have a name. Any columns in the derived table must have
unique names.

Related

partitioning an existing Table and using Like or Where clause with it

I'm trying to partition an existing table but I need to use Where or like clause.
The problem is I can't partition it cause every query I wrote, I get an error.
My last code is:
select *
into agg partition by range (subscriberid)
(subscriberid values LIKE '%42' on seg1)
from ncs_sub_unsub;
I've tried a lot of sources to get the answer how I can use a WHERE clause and the partition
Note: the Where and like clause is an initial part of the partitioning
My table : ncs_sub_unsub
The uniqure identifier is : subscriberid

I dont understand this Update query can you explain

so here is a little ms sql server query:
update tblSaleReturnMain set sync=0
from tblSaleOrderMain s join tblSaleReturnMain r on r.ID=s.intReturnOrderId
where s.sync=0
it updates my "tblSaleReturnMain" table just fine, also I wrote this query myself, but I dont know why it works. My question is, with all the many join-ed tables that I could reference after the "from" clause, and all the possible data that can be produced, how does this query know that the tblSaleReturnMain mentioned in "update tblSaleReturnMain .." is the same that is being filtered in join statement? Is that always like a protocol, like we mention a table before the "set" keyword and do not give it an alias, but then go on filtering/joining its data any way we like, and what remains in a resultset is what the "set" statement will apply to?
My question is specifically for Update statements that have JOINS after the FROM keyword.
Also this question is not about "how to use join in Update statement", because I already did that successfully above.
Yes, as long as you only use the target table once in the FROM SQL Server will assume it is the same table reference. From the docs (emphasis mine):
FROM <table_source>
Specifies that a table, view, or derived table source is used to provide the criteria for the update operation. For more information, see FROM (Transact-SQL).
If the object being updated is the same as the object in the FROM clause and there is only one reference to the object in the FROM clause, an object alias may or may not be specified. If the object being updated appears more than one time in the FROM clause, one, and only one, reference to the object must not specify a table alias. All other references to the object in the FROM clause must include an object alias.
If you reference the same table more than once and try to update it using just the table name rather than the alias, you'll get an error along the lines of:
Msg 8154 Level 16 State 1 Line 2
The table 'tblSaleReturnMain ' is ambiguous.
You can reference the same table more than once, but if doing so you must use the alias as the table_or_view_name, e.g.
UPDATE Alias
SET Col = 1
FROM dbo.T1 AS Alias
INNER JOIN dbo.T1 AS Alias2
ON Alias.ID = Alias2.ID;
Examples on DB<>Fiddle
I personally always use the alias regardless of whether the full table reference would be ambiguous.
SQL Server's UPDATE ... FROM syntax is non-standard and confusing.
Much better to write a CTE, examine the results, and then update the CTE, eg:
with q as
(
select r.sync
from tblSaleOrderMain s
join tblSaleReturnMain r
on r.ID=s.intReturnOrderId
where s.sync=0
)
update q set sync = 0

Automatically produce aliases for all columns in SELECT statement

I'm using Microsoft Query to pull data from MS SQL Server to Excel. Many of my tables have the same column names, for example:
[task].[active]
[user].[active]
[task].[name]
[user].[name]
When I pivot in Excel, only the column names are shown. A pivot filter might have multiple fields called "active" which is very confusing.
I'd like to alias every column with the table name it's from, so that in the filter it would say "task_active" and "user_active". My Excel SELECT statement would be:
SELECT active AS task_active, name AS task_name FROM task...
Is there a quick way to prepend the table name to an alias using a formatting tool? I have Apex SQL Refactor, and Notepad++ but I haven't found a way to do this without having to manually type all of the column names again.
If you populate resultset to datatable then datatable to excel then it will automatically change duplicate column name to col1,col2 etc.
This is not your requirement.you want it to be specific.
Method 1 . Create temp table with desire column name
Insert the result in #temp table
Return #temp table result set
Method 2 : Use dynamic query.
Wht your real query look like ?

How to use a recursive CTE in a check constraint?

I'm trying to create a check constraint on a table so that ParentID is never a descendant of current record
For instance, I have a table Categories, with the following fields ID, Name, ParentID
I have the following CTE
WITH Children AS (SELECT ID AS AncestorID, ID, ParentID AS NextAncestorID FROM Categories UNION ALL SELECT Categories.ID, Children.ID, Categories.ParentID FROM Categories JOIN Children ON Categories.ID = Children.NextAncestorID) SELECT ID FROM Children where AncestorID =99
The results here are correct, but when I try to add it as a constraint to the table like this:
ALTER TABLE dbo.Categories ADD CONSTRAINT CK_Categories CHECK (ParentID NOT IN(WITH Children AS (SELECT ID AS AncestorID, ID, ParentID AS NextAncestorID FROM Categories UNION ALL SELECT Categories.ID, Children.ID, Categories.ParentID FROM Categories JOIN Children ON Categories.ID = Children.NextAncestorID) SELECT ID FROM Children where AncestorID =ID))
I get the following error:
Incorrect syntax near the keyword 'with'. If this statement is a
common table expression, an xmlnamespaces clause or a change tracking
context clause, the previous statement must be terminated with a
semicolon.
Adding a semicolon before the WITH, didn't help.
What would be the correct way to do this?
Thanks!
Per the SQL Server documentation on column constraints:
CHECK
Is a constraint that enforces domain integrity by limiting the possible values that can be entered into a column or columns.
logical_expression
Is a logical expression used in a CHECK constraint and returns TRUE or FALSE. logical_expression used with CHECK constraints cannot reference another table but can reference other columns in the same table for the same row. The expression cannot reference an alias data type.
(The above was quoted from the SQL Server 2017 version of the documentation, but the general principle applies to all previous versions as well, and you didn't state what version you are working with.)
The important part here is the "cannot reference another table, but can reference other columns in the same table for the same row" (emphasis added). A CTE would count as another table.
As such, you can't have a complex query like a CTE used for a CHECK constraint.
Like Saman suggested, if you want to check against existing data in other rows, and it must be in the DB layer, you could do it as a trigger.
However, triggers have their own drawbacks (e.g. issues with discoverability, behavior that is unexpected by those who are unaware of the trigger's presence).
As Sami suggested in their comment, another option is a UDF, but that's not w/o its own issues, potentially with both performance and stability according to the answers on this question about this approach in SQL Server 2008. It's probably still applicable to later versions as well.
If possible, I would say it's usually best to move that logic into the application layer. I see from your comment that you already have "client-side" validation. If there is an app server between that client and the database server (such as in a web app), I would suggest putting that additional validation there (in the app server) instead of in the database.

SQL Updatable View with joined tables

I have a view that looks similar to this,
SELECT dbo.Staff.StaffId, dbo.Staff.StaffName, dbo.StaffPreferences.filter_type
FROM dbo.Staff LEFT OUTER JOIN
dbo.StaffPreferences ON dbo.Staff.StaffId = dbo.StaffPreferences.StaffId
I'm trying to update StaffPreferences.filter_type using,
UPDATE vw_Staff SET filter_type=1 WHERE StaffId=25
I have read this in an MSDN article,
Any modifications, including UPDATE, INSERT, and DELETE statements,
must reference columns from only one base table.
Does this mean that I can only update fields in dbo.Staff (which is all I can currently achieve) In this context does the definition of 'base table' not extend to any subsequently joined tables?
Your statement should work just fine since you are only modifying column(s) from one table (StaffPreferences).
If you tried to update a columns from different tables in the same update statement you would get an error.
Msg 4405, Level 16, State 1, Line 7
View or function 'v_ViewName' is not updatable because the modification affects multiple base tables.
The rules for updatable join views are as follows:
General Rule
Any INSERT, UPDATE, or DELETE operation on a join view can modify only
one underlying base table at a time.
UPDATE Rule All updatable columns of a join view must map to
columns of a key-preserved table. See "Key-Preserved Tables" for a
discussion of key-preserved tables. If the view is defined with the
WITH CHECK OPTION clause, then all join columns and all columns of
repeated tables are non-updatable.
DELETE Rule
Rows from a join view can be deleted as long as there is exactly one
key-preserved table in the join. If the view is defined with the WITH
CHECK OPTION clause and the key preserved table is repeated, then the
rows cannot be deleted from the view.
INSERT Rule An INSERT statement must not explicitly or
implicitly refer to the columns of a nonkey preserved table. If the
join view is defined with the WITH CHECK OPTION clause, INSERT
statements are not permitted.
http://download.oracle.com/docs/cd/B10501_01/server.920/a96521/views.htm#391
I think you can see some of the problems that might occur if there's a row in Staff with StaffId 25, but no matching row in StaffPreferences. There are various right things you could do (preserve the appearance that this is a table, perform an insert in StaffPreferences; reject the update; etc).
I think at this point, the SQL Server engine will give up, and you'll have to write a trigger that implements the behaviour you want (whatever that may be. You need to consider all of the cases for the join working/not working)
Here is how I solved it.
In my case it was table, not a view, but I needed to find the schema id that referenced the table in the data construction in a reference table, say called our_schema.
I ran the following:
select schemaid from our_schema where name = "MY:Form"
This gave me the id as 778 (example)
Then I looked where this ID was showing up with a prefix of T, B, or H.
In our case we have Table, Base and History tables where the data is stored.
I then ran:
delete from T778
delete from B778
delete from H778
This allowed me to delete the data and bypass that restriction.

Resources