Basically its what the title says. This is my code.
USE Assignment2;
GO
/* Player View (2 marks)
Create a view which shows the following details of all players:
• The ID number of the player
• The first name and surname of the player concatenated and given an alias of “full_name”
• The team ID number of the player (if applicable)
• The team name of the player (if applicable)
• The coach ID number of the player (if applicable)
• The name of the player’s coach (if applicable)
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that players without teams or coaches are still included in the results.
*/
-- Write your Player View here
PRINT 'Creating Player View'
CREATE VIEW playerView AS
SELECT player.id, player.firstName + ' ' + player.surname AS 'Full name', player.team, team.name, player.coach, coach.firstName, coach.surname
FROM player
LEFT OUTER JOIN team
ON player.team = team.id
LEFT OUTER JOIN player as coach
ON player.coach = coach.id;
GO
/* Race View (3 marks)
Create a view which shows the following details of all races:
• All of the columns in the race table
• The name of the race type, course and team involved in the race
• The full name of the player observing the race and the full name of the MVP (if applicable)
• A calculated column with an alias of “unpenalised_score”, which adds the points penalised to the final score
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that races without MVPs are still included in the results.
*/
-- Write your Race View here
PRINT 'Creating Race View'
CREATE VIEW raceView AS
SELECT race.id, race.dateOfRace, race.raceType, raceType.name AS raceTypeName, race.course, course.name AS courseName, race.team, team.name AS teamName, race.observer, obs.firstName + ' ' + obs.surname AS observer_name, race.mvp, mvp.firstName + ' ' + mvp.surname AS mvp_name, race.pointsPenalised, race.finalScore + race.pointsPenalised AS unpenalised_score, race.finalScore
FROM race
INNER JOIN raceType
ON race.raceType = raceType.id
INNER JOIN course
ON race.course = course.id
INNER JOIN team
ON race.team = team.id
LEFT OUTER JOIN player AS mvp
ON race.mvp = mvp.id
LEFT OUTER JOIN player AS obs
ON race.observer = obs.id;
GO
SELECT *
FROM playerView
SELECT *
FROM raceView
/* Additional Information:
The views are very convenient replacements for the tables they represent, as they include the names and calculated values that you will often need in queries.
You are very much encouraged to use the views to simplify the queries that follow. You can use a view in a SELECT statement in exactly the same way as you can use a table.
If you wish to create additional views to simplify the queries which follow, include them in this file.
*/
When I run each CREATE VIEW
separately, it seems to run it correctly with no errors. But when I try to run the entire script, it gives me this error.
Msg 111, Level 15, State 1, Line 20
‘CREATE VIEW’ must be the first statement in a query batch.
Msg 111, Level 15, State 1, Line 15
‘CREATE VIEW’ must be the first statement in a query batch.
Msg 208, Level 16, State 1, Line 2
Invalid object name ‘playerView’.
Before attempting to run this script, I first delete database, recreate the tables, populate them and then run this script.
Any ideas where I’m going wrong?
It’s not so much that it must be the first statement in the batch, but rather that it must be the only statement in the batch. For the same reason CREATE PROCEDURE
, CREATE FUNCTION
, etc. all have to be in their own batch … they need to be compiled independently of other code. One reason is to ensure that anything in the batch created before the object actually exists when it is created, and anything that refers to the object afterward has something to point to. Another is to help prevent this stuff:
-- some other code here
CREATE PROCEDURE dbo.whatever
AS
-- procedure code here
-- some other code here
We don’t want «some other code here» to be included in the definition of the stored procedure. We also wouldn’t know what to do with this:
CREATE PROCEDURE dbo.proc1
AS
-- some code here
-- a comment here
CREATE PROCEDURE dbo.proc2
AS
Since we can legally place comments before CREATE PROCEDURE
, how does the parser know which object the comment belongs to?
And for the nit-picky, the same thing applies to views. (Note that a procedure was used in the example simply because a procedure can contain multiple statements while a view can’t; and a procedure with multiple statements is far more common than a view with multiple comments.) But we can demonstrate the same type of problem — ask yourself if you don’t separate the two views into their own batches, how do you know which view should own comment4
?
-- comment1
CREATE VIEW dbo.view1
AS
-- comment2
SELECT
-- comment3
* from sys.objects
-- comment4
CREATE VIEW dbo.view2
AS
-- comment5
SELECT
-- comment6
* from sys.objects
In Management Studio, you work around this by placing a GO
between object scripts. Note that GO
is not T-SQL, it is an app-specific batch separator; from other interfaces, you will need to transmit your batches separately in other ways.
Again, the answer is in the first sentence: a script to create or alter any module in SQL Server — including views, procedures, functions, and triggers — must be the only statement in the batch.
In SQL Server, a batch is a group of one or more T-SQL statements sent at the same time from an application to SQL Server for execution.
If you encounter an error like this:
Msg 111, Level 15, State 1, Line 2
'CREATE VIEW' must be the first statement in a query batch.
It’s probably because you’re combining the statement with other statements in the same batch, which is not allowed in batches.
The first part of the error message will depend on the actual statement that you’re using in your batch. In my case it’s CREATE VIEW
, but it could just as easily be CREATE PROCEDURE
, CREATE FUNCTION
, etc if those are the statements you’re using.
Example
Here’s an example of some code that would cause this error:
DROP VIEW IF EXISTS vAllCustomers;
CREATE VIEW vAllCustomers AS
SELECT * FROM Customers;
Result:
Msg 111, Level 15, State 1, Line 3 'CREATE VIEW' must be the first statement in a query batch.
In my case, I’m trying to run two statements; a DROP VIEW
statement and a CREATE VIEW
statement.
The rules of a T-SQL batch state that the CREATE VIEW
statement cannot be combined with other statements in the same batch.
In other words, CREATE VIEW
can be the only statement in its batch.
How to Fix the Error
We can fix the above error by simply adding a batch separator after the first statement.
In SQL Server, the GO
keyword signals the end of a batch. More specifically, SQL Server utilities interpret GO
as a signal that they should send the current batch of T-SQL statements to an instance of SQL Server.
So we could change the previous statement to this:
DROP VIEW IF EXISTS vAllCustomers;
GO
CREATE VIEW vAllCustomers AS
SELECT * FROM Customers;
GO
Adding GO
fixes the issue by separating the statements into two separate batches.
Note that GO
is not actually part of T-SQL. It’s a command that is recognised by SQL Server utilities for the purpose of separating statements into batches.
You may be able to change the batch separator, depending on the tool you use to connect to SQL Server. For example, in SSMS, you can find this option by going to: Tools > Options > Query Execution > SQL Server and look for an option that says something like “Specify a word or character that can be used to separate batches”.
Problem
When you’re executing a CREATE/ALTER statement to create a procedure/view/function/trigger, you get one of the following errors:
‘CREATE/ALTER PROCEDURE’ must be the first statement in a query batch
‘CREATE VIEW’ must be the first statement in a query batch.
‘CREATE FUNCTION’ must be the first statement in a query batch.
‘CREATE TRIGGER’ must be the first statement in a query batch.
You can’t execute these CREATE/ALTER statements with other statements.
Solution
The solution is to execute the CREATE/ALTER statement separately from other statements. How you do that depends on if you’re using SSMS/sqlcmd/osql or executing from C#.
If you’re executing from SSMS (or sqlcmd/osql)
Add the keyword GO right before CREATE statement. This is the default batch separator in SSMS. It splits the query into multiple batches. In other words, it executes the CREATE statement by itself in its own batch, therefore solving the problem of it needing to be the first statement in a batch. Here’s an example:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'spGetAllPosts') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].spGetAllPosts
GO
CREATE PROCEDURE [dbo].spGetAllPosts
AS
BEGIN
SELECT * FROM Posts
END
Code language: SQL (Structured Query Language) (sql)
If you’re executing from C#
You can’t use the GO keyword in C#. Instead you have to execute the two queries separately. The best way to do that is to execute the first part, then change the CommandText and execute the second part.
using System.Data.SqlClient;
string dropProcQuery =
@"IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'spGetAllPosts') AND type in (N'P', N'PC'))
DROP PROCEDURE[dbo].spGetAllPosts";
string createProcQuery =
@"CREATE PROCEDURE [dbo].spGetAllPosts
AS
BEGIN
SELECT * FROM Posts
END";
using (var con = new SqlConnection(ConnectionString))
{
using (var cmd = new SqlCommand(dropProcQuery, con))
{
//Execute the first statement
con.Open();
cmd.ExecuteNonQuery();
//Then execute the CREATE statement
cmd.CommandText = createProcQuery;
cmd.ExecuteNonQuery();
}
}
Code language: C# (cs)
В основном это то, что говорится в названии. Это мой код.
USE Assignment2;
GO
/* Player View (2 marks)
Create a view which shows the following details of all players:
• The ID number of the player
• The first name and surname of the player concatenated and given an alias of "full_name"
• The team ID number of the player (if applicable)
• The team name of the player (if applicable)
• The coach ID number of the player (if applicable)
• The name of the player’s coach (if applicable)
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that players without teams or coaches are still included in the results.
*/
-- Write your Player View here
PRINT 'Creating Player View'
CREATE VIEW playerView AS
SELECT player.id, player.firstName + ' ' + player.surname AS 'Full name', player.team, team.name, player.coach, coach.firstName, coach.surname
FROM player
LEFT OUTER JOIN team
ON player.team = team.id
LEFT OUTER JOIN player as coach
ON player.coach = coach.id;
GO
/* Race View (3 marks)
Create a view which shows the following details of all races:
• All of the columns in the race table
• The name of the race type, course and team involved in the race
• The full name of the player observing the race and the full name of the MVP (if applicable)
• A calculated column with an alias of "unpenalised_score", which adds the points penalised to the final score
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that races without MVPs are still included in the results.
*/
-- Write your Race View here
PRINT 'Creating Race View'
CREATE VIEW raceView AS
SELECT race.id, race.dateOfRace, race.raceType, raceType.name AS raceTypeName, race.course, course.name AS courseName, race.team, team.name AS teamName, race.observer, obs.firstName + ' ' + obs.surname AS observer_name, race.mvp, mvp.firstName + ' ' + mvp.surname AS mvp_name, race.pointsPenalised, race.finalScore + race.pointsPenalised AS unpenalised_score, race.finalScore
FROM race
INNER JOIN raceType
ON race.raceType = raceType.id
INNER JOIN course
ON race.course = course.id
INNER JOIN team
ON race.team = team.id
LEFT OUTER JOIN player AS mvp
ON race.mvp = mvp.id
LEFT OUTER JOIN player AS obs
ON race.observer = obs.id;
GO
SELECT *
FROM playerView
SELECT *
FROM raceView
/* Additional Information:
The views are very convenient replacements for the tables they represent, as they include the names and calculated values that you will often need in queries.
You are very much encouraged to use the views to simplify the queries that follow. You can use a view in a SELECT statement in exactly the same way as you can use a table.
If you wish to create additional views to simplify the queries which follow, include them in this file.
*/
Когда я запускаю каждый CREATE VIEW
отдельно, он, кажется, запускает его правильно, без ошибок. Но когда я пытаюсь запустить весь script, он дает мне эту ошибку.
Msg 111, уровень 15, состояние 1, строка 20
«CREATE VIEW» должен быть первым оператором в пакете запросов.
Msg 111, уровень 15, состояние 1, строка 15
«CREATE VIEW» должен быть первым оператором в пакете запросов.
Msg 208, уровень 16, состояние 1, строка 2
Недопустимое имя объекта ‘playerView’.
Прежде чем пытаться запустить этот script, я сначала удаляю базу данных, воссоздаю таблицы, заполняю их, а затем запускаю этот script.
Любые идеи, в которых я ошибаюсь?
Ответ 1
введите GO
после PRINT 'Creating Player View'
и он должен работать:
PRINT 'Creating Player View'
GO
CREATE VIEW playerView AS
Ответ 2
Пакеты разделяются словом GO
— которое является инструкцией для клиентских инструментов, а не SQL Server, в частности, чтобы сообщить этим инструментам, как разделить ваш запрос на партии.
Ошибка говорит вам, что CREATE VIEW
должен быть первым оператором в пакете:
USE Assignment2;
GO
/* Player View (2 marks)
Create a view which shows the following details of all players:
• The ID number of the player
• The first name and surname of the player concatenated and given an alias of "full_name"
• The team ID number of the player (if applicable)
• The team name of the player (if applicable)
• The coach ID number of the player (if applicable)
• The name of the player’s coach (if applicable)
Creating this view requires a select statement using multiple joins and concatenation of names.
Make sure that you use the appropriate type of join to ensure that players without teams or coaches are still included in the results.
*/
-- Write your Player View here
PRINT 'Creating Player View'
GO -->-- New GO here
CREATE VIEW playerView AS
Итак, я добавил GO
до CREATE VIEW
Ответ 3
Поместите код CREATE VIEW внутри EXECUTE
SOME CONDITION..
EXECUTE('CREATE VIEW vwName...')
Ответ 4
Это обычно происходит, потому что, имея возможность создавать VIEW или любой DBO, вам нужно, чтобы весь script находился внутри транзакции или вам нужно включить
SET QUOTED_IDENTIFIER.
т
USE [yourdatabase]
GO
SET NUMERIC_ROUNDABORT, IMPLICIT_TRANSACTIONS OFF
SET ANSI_PADDING, ANSI_NULLS, QUOTED_IDENTIFIER, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
...
...
-- Write your Race View here
PRINT 'Creating Race View'
GO
CREATE VIEW raceView AS
SELECT race.id, race.dateOfRace, race.raceType, raceType.name AS raceTypeName, race.course, course.name AS courseName, race.team, team.name AS teamName, race.observer, obs.firstName + ' ' + obs.surname AS observer_name, race.mvp, mvp.firstName + ' ' + mvp.surname AS mvp_name, race.pointsPenalised, race.finalScore + race.pointsPenalised AS unpenalised_score, race.finalScore
FROM race
INNER JOIN raceType
ON race.raceType = raceType.id
INNER JOIN course
ON race.course = course.id
INNER JOIN team
ON race.team = team.id
LEFT OUTER JOIN player AS mvp
ON race.mvp = mvp.id
LEFT OUTER JOIN player AS obs
ON race.observer = obs.id;
GO
IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT > 0 ROLLBACK SET NOEXEC ON END
GO
IF @@TRANCOUNT>0 COMMIT TRANSACTION
GO
SET NOEXEC OFF