Sunucu sorumlusu, SQL Server MS 2012'deki mevcut güvenlik bağlamı altında veritabanına erişemiyor


103

Hosting sunucumun veritabanına SQL Server Management Studio üzerinden erişmeye çalışıyorum, giriş yapana kadar her şey yolunda ama komutu kullandığımda use myDatabasebana şu hatayı veriyor:

The server principal "****" is not able to access the database "****" under the current security context.

Aradım ve barındırma hizmeti sağlayıcıları sorun için bu düzeltmeyi listeledi .

Ancak bu benim için çalışmıyor büyük olasılıkla SQL Server Management Studio 2008 için, ancak SQL Server Management Studio 2012 kullanıyorum.

Bu bir problem olabilir mi? Ve evet ise, kimse bana SSMS 2012'deki alternatifini söyleyebilir mi?


3
"Barındırma hizmeti sağlayıcıları"? Adanmış mıyız yoksa ortak mı konuşuyoruz? Paylaşılan bir barındırma sunucusuysa, yardım için barındırma sağlayıcınızla iletişime geçmenizi şiddetle tavsiye ederim. Paylaşılan bir barındırma ortamında SQL herkesin bildiği gibi hatalı ve sorunludur. Ürünle hiçbir ilgisi yoktur, ancak barındırma sağlayıcılarının sunuculara uyguladıkları politikalar. Her barındırma şirketinin SQL'den yararlanmanın kendi yolu vardır ya da öyle görünüyor.
Techie Joe

Yanıtlar:


80

Kullanıcınızın oturum açmaya çalıştığınız DB ile eşleşip eşleşmediğini kontrol edin.


76
bunu nasıl yaptın?
Graham

3
@Graham Kullanıcıyı kontrol etmek için SQL Server Management Studio'yu kullanın veya şu yanıtı görün: stackoverflow.com/a/9356725/804773
Grambot

5
Tetikleyicileri aramanızı öneririm, bu mesajı almamın nedeni buydu, kullanıcımın yetkilendirilmediği başka bir veritabanında bazı şeyler yapan bir tetikleyici vardı.
DanielV

1
OP'nin hatasına ve bu cevaba tanklara çarptım, Azure SQL Veritabanına bağlanan bağlantı dizimdeki Veritabanı Adında aptalca bir yazım hatası olduğunu fark ettim. Veritabanı Adınız doğruysa, Master'a erişmeniz gerekmez. Yanlışsa, o zaman (benim durumumda) Entity Framework'ün (6.1.3) bazı ek bilgiler için Master'a bağlanarak ekstra akıllı olmaya çalıştığını düşünüyorum (ancak bu EF ile ilgisiz olabilir - emin değilim). Ama benim çözümüm, bağlantı dizimin doğru olduğundan emin olmaktı. Kötü bir veritabanı adı için çok farklı bir hata bekliyordum. : - /
Jaxidian

2
@ DanielV'nin yorumuna eklemek için, ayrıca herhangi bir sabit kodlanmış veritabanı adı için Depolanan Prosedürleri kontrol edin. Benim durumumda düzeltildi (yaklaşık 20 saklı yordamın değiştirilmesi gerekiyordu).
Demonslay335

26

PROD ortamımızda SSRS'ye bir rapor dağıtırken aynı hatayı aldık. Sorunun bir “kullanım” ifadesiyle yeniden üretilebileceği tespit edildi. Çözüm, kullanıcının GUID hesap referansını söz konusu veritabanıyla yeniden senkronize etmekti (yani, bir db'yi geri yükledikten sonra yaptığınız gibi "sp_change_users_login" kullanarak). Tüm hesapları yeniden senkronize etmek için bir hisse senedi (imleçle çalışan) komut dosyası eklenmiştir:

USE <your database>
GO

-------- Reset SQL user account guids ---------------------
DECLARE @UserName nvarchar(255) 
DECLARE orphanuser_cur cursor for 
      SELECT UserName = su.name 
      FROM sysusers su
      JOIN sys.server_principals sp ON sp.name = su.name
      WHERE issqluser = 1 AND
            (su.sid IS NOT NULL AND su.sid <> 0x0) AND
            suser_sname(su.sid) is null 
      ORDER BY su.name 

OPEN orphanuser_cur 
FETCH NEXT FROM orphanuser_cur INTO @UserName 

WHILE (@@fetch_status = 0)
BEGIN 
--PRINT @UserName + ' user name being resynced' 
exec sp_change_users_login 'Update_one', @UserName, @UserName 
FETCH NEXT FROM orphanuser_cur INTO @UserName 
END 

CLOSE orphanuser_cur 
DEALLOCATE orphanuser_cur

2
Benim için çalıştı Teşekkür ederim. SQL sunucu kimlik doğrulamasına sahip bir veritabanını test sunucuma kopyalamıştım ve erişilemez durumdaydı. Şimdi öyle
MikeH

1
Kullanıcı veritabanında mevcutsa ancak Oturum Açma için bir eşlemeyi sürdürmede başarısız olursa, söz konusu Kullanıcıyı SSMS Nesne Gezgini aracılığıyla silip ardından Oturum Açmayı yeniden eşlemek benim için çalıştı. Aksi takdirde yukarıda önerilen çözümün alınması gerekeceğinden şüpheleniyorum.
jjt

11

Bu benim için çalıştı:

use <Database>
EXEC  sp_change_users_login @Action='update_one', @UserNamePattern='<userLogin>',@LoginName='<userLogin>';

Sorun şu şekilde görselleştirilebilir:

SELECT sid FROM sys.sysusers WHERE name = '<userLogin>'
SELECT sid FROM sys.syslogins WHERE name = '<userLogin>';

2
Bu benim için düzeltti. Teşekkürler ! "Sorun ile görselleştirilebilir" -> Farklı bir hash döndürürlerse, bir sorun vardır ve yukarıdaki sorgu bunları senkronize eder.
bezout

10

Bu sorunla boğuşmak için epey bir zaman harcadım ve sonra bağlantımı hedeflediğim hangi veri tabanını unuttuğum için basit bir hata yaptığımı fark ettim. Kimlik bilgilerini girmek için standart SQL Server bağlantı penceresini kullanıyordum:

SQL Server Bağlantı Penceresi

Bağlanmak için doğru veritabanını seçtiğimi doğrulamak için Bağlantı Özellikleri sekmesini kontrol etmem gerekti. Buradaki Veritabanına bağlan seçeneğini yanlışlıkla bir önceki oturumdan bir seçime ayarlı bırakmıştım . Bu yüzden bağlanmaya çalıştığımı düşündüğüm veritabanına bağlanamadım.

Bağlantı Özellikleri

Bağlantı Özellikleri ve diğer sekmelerin görünmesi Options >>için düğmeye tıklamanız gerektiğini unutmayın .


7

SQL Oturum Açma Bilgileri sunucu düzeyinde tanımlanır ve belirli veritabanlarında Kullanıcılar ile eşleştirilmelidir .

SSMS nesne gezgini'nde, değiştirmek istediğiniz sunucunun altında Güvenlik > Oturum Açmalar'ı genişletin , ardından "Oturum Açma Özellikleri" iletişim kutusunu açacak uygun kullanıcıyı çift tıklayın.

Sunucudaki tüm veritabanlarını mevcut bir eşlemeye sahip olanlar seçili olarak gösterecek olan Kullanıcı Haritalama'yı seçin . Buradan ek veritabanları seçebilir (ve kullanıcının her veritabanında ait olması gereken rolleri seçtiğinizden emin olun), ardından eşlemeleri eklemek için Tamam'ı tıklayabilirsiniz .

görüntü açıklamasını buraya girin

Bu eşlemelerin bağlantısı, bir geri yükleme veya benzer işlemden sonra kesilebilir. Bu durumda, kullanıcı hala veritabanında olabilir ancak gerçekte bir oturum açma ile eşlenmemiştir. Böyle bir durumda, girişi geri yüklemek için aşağıdakileri çalıştırabilirsiniz:

USE {database};
ALTER USER {user} WITH login = {login}

Ayrıca DB kullanıcısını silebilir ve Oturum Açma Özellikleri iletişim kutusundan yeniden oluşturabilirsiniz, ancak tüm rol üyeliklerinin veya diğer ayarların yeniden oluşturulması gerekir.


4

Benim durumumda, mesaja yanlışlıkla veritabanı adını "nesne adı" na dahil eden bir eşanlamlı neden oldu. Veritabanını yeni bir adla geri yüklediğimde, eşanlamlı hala eski DB adını gösteriyordu. Kullanıcının eski DB'de izinleri olmadığı için mesaj belirdi. Düzeltmek için, nesne adını veritabanı adıyla nitelendirmeden eşanlamlıyı bıraktım ve yeniden oluşturdum:

    USE [new_db]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
DROP SYNONYM [dbo].[synTable]
GO

/****** Object:  Synonym [dbo].[synTable]    Script Date: 10/15/2015 9:45:01 AM ******/
CREATE SYNONYM [dbo].[synTable] FOR [dbo].[tTheRealTable]
GO

2

Kullanıcı oturum açma ile doğru bir şekilde eşleştirilmesine rağmen aynı hatayı aldık.

Kullanıcıyı silmeye çalıştıktan sonra, birkaç SP'nin bu kullanıcı "ile çalıştır" içerdiği keşfedildi.

Sorun, bu SP'leri bırakarak, kullanıcıyı bırakarak, oturum açma ile bağlantılı kullanıcıyı yeniden oluşturarak ve SP'leri yeniden oluşturarak çözüldü.

Muhtemelen bu durumda yedekten geri yüklemeden (ilgili girişin olmadığı bir zamanda) veya toplu şema senkronizasyonundan (eğer kullanıcı yokmuş gibi yürütme ile bir SP oluşturmak mümkünse) olabilir. bu cevapla ilgili .


1
SP'ler ile ne demek istediğinizi biraz daha açabilir misiniz?
Scuba Steve

1
Saklı yordam. Bir SP oluştururken (proc xxx ... oluştur), SP'nin o anda oturum açmış olan kullanıcı yerine o kullanıcı çalıştırmış gibi çalışacağını belirten isteğe bağlı bir "<kullanıcı> olarak çalıştır" cümlesi vardır.
crokusek

1

Vb.net'te Server Management Objects (SMO) kullanırken aynı hatayla karşılaştım (C # ile aynı olduğundan eminim)

Techie Joe'nun ilk gönderiye yaptığı yorum, paylaşılan barındırmada birçok ek şeyin devam ettiği konusunda faydalı bir uyarı oldu. Anlaması biraz zaman aldı, ancak aşağıdaki kod, SQL veritabanlarına erişme yöntemlerinin nasıl çok spesifik olması gerektiğini gösteriyor. SMO çağrıları paylaşılan barındırma ortamında tam olarak spesifik olmadığında 'sunucu asıl ...' hatası ortaya çıkıyor gibi görünüyordu.

Kodun bu ilk bölümü yerel bir SQL Express sunucusuna karşıydı ve basit Windows Kimlik Doğrulamasına dayanıyordu. Bu örneklerde kullanılan tüm kodlar, bu Kod Projesi web sitesi makalesindeki Robert Kanasz'ın SMO öğreticisine dayanmaktadır :

  Dim conn2 = New ServerConnection()
  conn2.ServerInstance = "<local pc name>\SQLEXPRESS"
  Try
    Dim testConnection As New Server(conn2)
    Debug.WriteLine("Server: " + testConnection.Name)
    Debug.WriteLine("Edition: " + testConnection.Information.Edition)
    Debug.WriteLine(" ")

    For Each db2 As Database In testConnection.Databases
      Debug.Write(db2.Name & " - ")
      For Each fg As FileGroup In db2.FileGroups
        Debug.Write(fg.Name & " - ")
        For Each df As DataFile In fg.Files
          Debug.WriteLine(df.Name + " - " + df.FileName)
        Next
      Next
    Next
    conn2.Disconnect()

  Catch err As Exception
    Debug.WriteLine(err.Message)
  End Try

Yukarıdaki kod, yerel SQLEXPRESS sunucusundaki her veritabanı için .mdf dosyalarını bulur, çünkü kimlik doğrulama Windows tarafından yapılır ve tüm veritabanları için geniş.

Aşağıdaki kodda .mdf dosyaları için yinelenen 2 bölüm vardır. Bu durumda, yalnızca bir dosya grubunu arayan ilk yineleme çalışır ve yalnızca tek bir dosya bulur çünkü bağlantı, paylaşılan barındırma ortamındaki tek bir veritabanına bağlıdır.

Yukarıda çalışan yinelemenin bir kopyası olan ikinci yineleme, yazılma şekliyle Kullanıcı Kimliği / Parolanın geçerli olmadığı paylaşılan ortamda 1. veritabanına erişmeye çalıştığı için hemen boğulur. SQL sunucusu 'sunucu asıl ...' hatası şeklinde bir yetkilendirme hatası döndürür.

Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection
sqlConnection1.ConnectionString = "connection string with User ID/Password to a specific database in a shared hosting system. This string will likely also include the Data Source and Initial Catalog parameters"
Dim conn1 As New ServerConnection(sqlConnection1)
Try
  Dim testConnection As New Server(conn1)
  Debug.WriteLine("Server: " + testConnection.Name)
  Debug.WriteLine("Edition: " + testConnection.Information.Edition)
  Debug.WriteLine(" ")

  Dim db2 = testConnection.Databases("the name of the database to which the User ID/Password in the connection string applies")
  For Each fg As FileGroup In db2.FileGroups
    Debug.Write(fg.Name & " - ")
    For Each df As DataFile In fg.Files
      Debug.WriteLine(df.Name + " - " + df.FileName)
    Next
  Next

  For Each db3 As Database In testConnection.Databases
    Debug.Write(db3.Name & " - ")
    For Each fg As FileGroup In db3.FileGroups
      Debug.Write(fg.Name & " - ")
      For Each df As DataFile In fg.Files
        Debug.WriteLine(df.Name + " - " + df.FileName)
      Next
    Next
  Next

  conn1.Disconnect()

Catch err As Exception
  Debug.WriteLine(err.Message)
End Try

Bu ikinci yineleme döngüsünde, kod iyi derlenir, ancak SMO, kesin sözdizimi ile tam olarak doğru veritabanına erişecek şekilde ayarlanmadığı için bu girişim başarısız olur.

SMO'yu yeni öğrenirken, diğer yeni başlayanların da bu hatanın daha basit bir açıklaması olduğunu bilmekten memnun kalacaklarını düşündüm - sadece yanlış kodladık.


0

Veritabanı kullanıcısını oluştururken bir "Bağlan Ver" ifadesinin eksik olabileceğine inanıyorum.

Aşağıda, hem SQL Server DBMS'ye karşı bir oturum açma hem de veritabanına karşı bir kullanıcı oluşturmanız gerekecek tam kod parçacığı verilmiştir.

USE [master]
GO

CREATE LOGIN [SqlServerLogin] WITH PASSWORD=N'Passwordxyz', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
GO

USE [myDatabase]
GO

CREATE USER [DatabaseUser] FOR LOGIN [SqlServerLogin] WITH DEFAULT_SCHEMA=[mySchema]
GO

GRANT CONNECT TO [DatabaseUser]
GO

-- the role membership below will allow you to run a test "select" query against the tables in your database
ALTER ROLE [db_datareader] ADD MEMBER [DatabaseUser]
GO
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.